468 lines
15 KiB
Python
468 lines
15 KiB
Python
"""
|
|
Mobile API Views für React Native Integration
|
|
"""
|
|
|
|
from django.shortcuts import render
|
|
from django.http import JsonResponse
|
|
from django.contrib.auth.decorators import login_required
|
|
from django.views.decorators.csrf import csrf_exempt
|
|
from django.utils import timezone
|
|
from rest_framework.decorators import api_view, permission_classes
|
|
from rest_framework.permissions import IsAuthenticated
|
|
from rest_framework.response import Response
|
|
from rest_framework import status
|
|
from .models import MobileDevice, PushNotification, OfflineSync, MobileAnalytics, MobileCache, MobileSession
|
|
from .serializers import MobileDeviceSerializer, PushNotificationSerializer
|
|
import json
|
|
|
|
|
|
@api_view(['POST'])
|
|
@permission_classes([IsAuthenticated])
|
|
def register_device(request):
|
|
"""Mobile Device registrieren für Push Notifications"""
|
|
|
|
try:
|
|
data = request.data
|
|
device_token = data.get('device_token')
|
|
device_type = data.get('device_type', 'web')
|
|
|
|
if not device_token:
|
|
return Response({'error': 'Device token required'}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
# Device erstellen oder aktualisieren
|
|
device, created = MobileDevice.objects.get_or_create(
|
|
device_token=device_token,
|
|
defaults={
|
|
'user': request.user,
|
|
'device_type': device_type,
|
|
'device_name': data.get('device_name', ''),
|
|
'device_model': data.get('device_model', ''),
|
|
'os_version': data.get('os_version', ''),
|
|
'app_version': data.get('app_version', ''),
|
|
}
|
|
)
|
|
|
|
if not created:
|
|
# Device aktualisieren
|
|
device.user = request.user
|
|
device.device_type = device_type
|
|
device.device_name = data.get('device_name', device.device_name)
|
|
device.device_model = data.get('device_model', device.device_model)
|
|
device.os_version = data.get('os_version', device.os_version)
|
|
device.app_version = data.get('app_version', device.app_version)
|
|
device.is_active = True
|
|
device.save()
|
|
|
|
serializer = MobileDeviceSerializer(device)
|
|
return Response(serializer.data, status=status.HTTP_201_CREATED if created else status.HTTP_200_OK)
|
|
|
|
except Exception as e:
|
|
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
|
|
|
|
@api_view(['DELETE'])
|
|
@permission_classes([IsAuthenticated])
|
|
def unregister_device(request, device_token):
|
|
"""Mobile Device deregistrieren"""
|
|
|
|
try:
|
|
device = MobileDevice.objects.get(
|
|
device_token=device_token,
|
|
user=request.user
|
|
)
|
|
device.is_active = False
|
|
device.save()
|
|
|
|
return Response({'message': 'Device unregistered'}, status=status.HTTP_200_OK)
|
|
|
|
except MobileDevice.DoesNotExist:
|
|
return Response({'error': 'Device not found'}, status=status.HTTP_404_NOT_FOUND)
|
|
|
|
|
|
@api_view(['GET'])
|
|
@permission_classes([IsAuthenticated])
|
|
def get_user_devices(request):
|
|
"""User's Mobile Devices abrufen"""
|
|
|
|
devices = MobileDevice.objects.filter(user=request.user, is_active=True)
|
|
serializer = MobileDeviceSerializer(devices, many=True)
|
|
return Response(serializer.data)
|
|
|
|
|
|
@api_view(['POST'])
|
|
@permission_classes([IsAuthenticated])
|
|
def send_push_notification(request):
|
|
"""Push Notification senden"""
|
|
|
|
try:
|
|
data = request.data
|
|
user_id = data.get('user_id')
|
|
notification_type = data.get('notification_type')
|
|
title = data.get('title')
|
|
message = data.get('message')
|
|
data_payload = data.get('data', {})
|
|
|
|
if not all([user_id, notification_type, title, message]):
|
|
return Response({'error': 'Missing required fields'}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
# Get user's active devices
|
|
devices = MobileDevice.objects.filter(
|
|
user_id=user_id,
|
|
is_active=True
|
|
)
|
|
|
|
notifications = []
|
|
for device in devices:
|
|
notification = PushNotification.objects.create(
|
|
user_id=user_id,
|
|
device=device,
|
|
notification_type=notification_type,
|
|
title=title,
|
|
message=message,
|
|
data=data_payload
|
|
)
|
|
notifications.append(notification)
|
|
|
|
# Send actual push notification (would integrate with Firebase/APNS)
|
|
# send_push_notification_to_device(notifications)
|
|
|
|
serializer = PushNotificationSerializer(notifications, many=True)
|
|
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
|
|
|
except Exception as e:
|
|
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
|
|
|
|
@api_view(['POST'])
|
|
@permission_classes([IsAuthenticated])
|
|
def sync_offline_data(request):
|
|
"""Offline Data Sync für Mobile App"""
|
|
|
|
try:
|
|
data = request.data
|
|
sync_type = data.get('sync_type')
|
|
sync_data = data.get('data', {})
|
|
device_token = data.get('device_token')
|
|
|
|
if not sync_type or not device_token:
|
|
return Response({'error': 'Missing required fields'}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
# Get device
|
|
try:
|
|
device = MobileDevice.objects.get(
|
|
device_token=device_token,
|
|
user=request.user,
|
|
is_active=True
|
|
)
|
|
except MobileDevice.DoesNotExist:
|
|
return Response({'error': 'Device not found'}, status=status.HTTP_404_NOT_FOUND)
|
|
|
|
# Create sync record
|
|
sync = OfflineSync.objects.create(
|
|
user=request.user,
|
|
device=device,
|
|
sync_type=sync_type,
|
|
data=sync_data,
|
|
status='pending'
|
|
)
|
|
|
|
# Process sync based on type
|
|
if sync_type == 'orders':
|
|
# Sync orders
|
|
pass
|
|
elif sync_type == 'products':
|
|
# Sync products
|
|
pass
|
|
elif sync_type == 'auctions':
|
|
# Sync auctions
|
|
pass
|
|
|
|
sync.status = 'completed'
|
|
sync.synced_at = timezone.now()
|
|
sync.save()
|
|
|
|
return Response({
|
|
'sync_id': str(sync.id),
|
|
'status': sync.status,
|
|
'synced_at': sync.synced_at
|
|
}, status=status.HTTP_200_OK)
|
|
|
|
except Exception as e:
|
|
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
|
|
|
|
@api_view(['POST'])
|
|
@permission_classes([IsAuthenticated])
|
|
def track_analytics(request):
|
|
"""Mobile Analytics Event tracken"""
|
|
|
|
try:
|
|
data = request.data
|
|
event_type = data.get('event_type')
|
|
event_data = data.get('event_data', {})
|
|
session_id = data.get('session_id', '')
|
|
screen_name = data.get('screen_name', '')
|
|
device_token = data.get('device_token')
|
|
|
|
if not event_type or not device_token:
|
|
return Response({'error': 'Missing required fields'}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
# Get device
|
|
try:
|
|
device = MobileDevice.objects.get(
|
|
device_token=device_token,
|
|
user=request.user,
|
|
is_active=True
|
|
)
|
|
except MobileDevice.DoesNotExist:
|
|
return Response({'error': 'Device not found'}, status=status.HTTP_404_NOT_FOUND)
|
|
|
|
# Create analytics record
|
|
analytics = MobileAnalytics.objects.create(
|
|
user=request.user,
|
|
device=device,
|
|
event_type=event_type,
|
|
event_data=event_data,
|
|
session_id=session_id,
|
|
screen_name=screen_name
|
|
)
|
|
|
|
return Response({'analytics_id': str(analytics.id)}, status=status.HTTP_201_CREATED)
|
|
|
|
except Exception as e:
|
|
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
|
|
|
|
@api_view(['GET'])
|
|
@permission_classes([IsAuthenticated])
|
|
def get_mobile_products(request):
|
|
"""Mobile-optimierte Produktliste"""
|
|
|
|
from products.models import Product
|
|
from products.serializers import ProductSerializer
|
|
|
|
# Mobile-optimierte Filter
|
|
products = Product.objects.filter(is_active=True).select_related('category')
|
|
|
|
# Pagination
|
|
page = int(request.GET.get('page', 1))
|
|
per_page = int(request.GET.get('per_page', 20))
|
|
|
|
start = (page - 1) * per_page
|
|
end = start + per_page
|
|
|
|
products_page = products[start:end]
|
|
serializer = ProductSerializer(products_page, many=True)
|
|
|
|
return Response({
|
|
'products': serializer.data,
|
|
'total': products.count(),
|
|
'page': page,
|
|
'per_page': per_page,
|
|
'has_next': end < products.count(),
|
|
'has_previous': page > 1
|
|
})
|
|
|
|
|
|
@api_view(['GET'])
|
|
@permission_classes([IsAuthenticated])
|
|
def get_mobile_auctions(request):
|
|
"""Mobile-optimierte Auktionen"""
|
|
|
|
from auction.models import Auction
|
|
from auction.serializers import AuctionSerializer
|
|
|
|
auctions = Auction.objects.filter(status='active').select_related('created_by')
|
|
|
|
# Pagination
|
|
page = int(request.GET.get('page', 1))
|
|
per_page = int(request.GET.get('per_page', 10))
|
|
|
|
start = (page - 1) * per_page
|
|
end = start + per_page
|
|
|
|
auctions_page = auctions[start:end]
|
|
serializer = AuctionSerializer(auctions_page, many=True)
|
|
|
|
return Response({
|
|
'auctions': serializer.data,
|
|
'total': auctions.count(),
|
|
'page': page,
|
|
'per_page': per_page,
|
|
'has_next': end < auctions.count(),
|
|
'has_previous': page > 1
|
|
})
|
|
|
|
|
|
@api_view(['POST'])
|
|
@permission_classes([IsAuthenticated])
|
|
def start_session(request):
|
|
"""Mobile Session starten"""
|
|
|
|
try:
|
|
data = request.data
|
|
device_token = data.get('device_token')
|
|
session_id = data.get('session_id')
|
|
|
|
if not device_token or not session_id:
|
|
return Response({'error': 'Missing required fields'}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
# Get device
|
|
try:
|
|
device = MobileDevice.objects.get(
|
|
device_token=device_token,
|
|
user=request.user,
|
|
is_active=True
|
|
)
|
|
except MobileDevice.DoesNotExist:
|
|
return Response({'error': 'Device not found'}, status=status.HTTP_404_NOT_FOUND)
|
|
|
|
# Create or update session
|
|
session, created = MobileSession.objects.get_or_create(
|
|
session_id=session_id,
|
|
defaults={
|
|
'user': request.user,
|
|
'device': device,
|
|
'is_active': True
|
|
}
|
|
)
|
|
|
|
if not created:
|
|
session.is_active = True
|
|
session.save()
|
|
|
|
return Response({
|
|
'session_id': session.session_id,
|
|
'started_at': session.started_at
|
|
}, status=status.HTTP_200_OK)
|
|
|
|
except Exception as e:
|
|
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
|
|
|
|
@api_view(['POST'])
|
|
@permission_classes([IsAuthenticated])
|
|
def end_session(request, session_id):
|
|
"""Mobile Session beenden"""
|
|
|
|
try:
|
|
session = MobileSession.objects.get(
|
|
session_id=session_id,
|
|
user=request.user,
|
|
is_active=True
|
|
)
|
|
|
|
session.end_session()
|
|
|
|
return Response({
|
|
'session_id': session.session_id,
|
|
'duration': session.duration,
|
|
'ended_at': session.ended_at
|
|
}, status=status.HTTP_200_OK)
|
|
|
|
except MobileSession.DoesNotExist:
|
|
return Response({'error': 'Session not found'}, status=status.HTTP_404_NOT_FOUND)
|
|
|
|
|
|
@api_view(['POST'])
|
|
@permission_classes([IsAuthenticated])
|
|
def report_error(request):
|
|
"""Mobile App Error melden"""
|
|
|
|
try:
|
|
data = request.data
|
|
error_level = data.get('error_level', 'error')
|
|
error_type = data.get('error_type')
|
|
error_message = data.get('error_message')
|
|
stack_trace = data.get('stack_trace', '')
|
|
device_token = data.get('device_token')
|
|
|
|
if not error_type or not error_message or not device_token:
|
|
return Response({'error': 'Missing required fields'}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
# Get device
|
|
try:
|
|
device = MobileDevice.objects.get(
|
|
device_token=device_token,
|
|
user=request.user,
|
|
is_active=True
|
|
)
|
|
except MobileDevice.DoesNotExist:
|
|
return Response({'error': 'Device not found'}, status=status.HTTP_404_NOT_FOUND)
|
|
|
|
# Create error record
|
|
error = MobileError.objects.create(
|
|
user=request.user,
|
|
device=device,
|
|
error_level=error_level,
|
|
error_type=error_type,
|
|
error_message=error_message,
|
|
stack_trace=stack_trace,
|
|
app_version=data.get('app_version', ''),
|
|
os_version=data.get('os_version', ''),
|
|
device_info=data.get('device_info', {})
|
|
)
|
|
|
|
return Response({'error_id': str(error.id)}, status=status.HTTP_201_CREATED)
|
|
|
|
except Exception as e:
|
|
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
|
|
|
|
@api_view(['GET'])
|
|
@permission_classes([IsAuthenticated])
|
|
def get_mobile_cache(request, cache_type):
|
|
"""Mobile Cache abrufen"""
|
|
|
|
try:
|
|
cache_key = request.GET.get('key', 'default')
|
|
|
|
cache = MobileCache.objects.filter(
|
|
user=request.user,
|
|
cache_type=cache_type,
|
|
cache_key=cache_key,
|
|
expires_at__gt=timezone.now()
|
|
).first()
|
|
|
|
if cache:
|
|
return Response({
|
|
'data': cache.cache_data,
|
|
'expires_at': cache.expires_at
|
|
})
|
|
else:
|
|
return Response({'data': None}, status=status.HTTP_404_NOT_FOUND)
|
|
|
|
except Exception as e:
|
|
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
|
|
|
|
@api_view(['POST'])
|
|
@permission_classes([IsAuthenticated])
|
|
def update_mobile_cache(request, cache_type):
|
|
"""Mobile Cache aktualisieren"""
|
|
|
|
try:
|
|
data = request.data
|
|
cache_key = data.get('key', 'default')
|
|
cache_data = data.get('data', {})
|
|
expires_in = data.get('expires_in', 3600) # Default 1 hour
|
|
|
|
expires_at = timezone.now() + timezone.timedelta(seconds=expires_in)
|
|
|
|
cache, created = MobileCache.objects.update_or_create(
|
|
user=request.user,
|
|
cache_type=cache_type,
|
|
cache_key=cache_key,
|
|
defaults={
|
|
'cache_data': cache_data,
|
|
'expires_at': expires_at
|
|
}
|
|
)
|
|
|
|
return Response({
|
|
'cache_id': str(cache.id),
|
|
'expires_at': cache.expires_at
|
|
}, status=status.HTTP_201_CREATED if created else status.HTTP_200_OK)
|
|
|
|
except Exception as e:
|
|
return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) |