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