217 lines
8.2 KiB
Python
217 lines
8.2 KiB
Python
"""
|
|
Mobile App Models für React Native API
|
|
"""
|
|
|
|
from django.db import models
|
|
from django.contrib.auth.models import User
|
|
from django.utils import timezone
|
|
import uuid
|
|
|
|
|
|
class MobileDevice(models.Model):
|
|
"""Mobile Device Registration für Push Notifications"""
|
|
|
|
DEVICE_TYPE_CHOICES = [
|
|
('ios', 'iOS'),
|
|
('android', 'Android'),
|
|
('web', 'Web'),
|
|
]
|
|
|
|
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
|
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='mobile_devices')
|
|
device_token = models.CharField(max_length=255, unique=True)
|
|
device_type = models.CharField(max_length=20, choices=DEVICE_TYPE_CHOICES)
|
|
device_name = models.CharField(max_length=100, blank=True)
|
|
device_model = models.CharField(max_length=100, blank=True)
|
|
os_version = models.CharField(max_length=50, blank=True)
|
|
app_version = models.CharField(max_length=20, blank=True)
|
|
is_active = models.BooleanField(default=True)
|
|
last_seen = models.DateTimeField(auto_now=True)
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|
|
|
class Meta:
|
|
ordering = ['-created_at']
|
|
verbose_name = 'Mobile Device'
|
|
verbose_name_plural = 'Mobile Devices'
|
|
|
|
def __str__(self):
|
|
return f"{self.user.username} - {self.device_type} ({self.device_name})"
|
|
|
|
|
|
class PushNotification(models.Model):
|
|
"""Push Notification Tracking"""
|
|
|
|
NOTIFICATION_TYPE_CHOICES = [
|
|
('order_status', 'Order Status'),
|
|
('auction_update', 'Auction Update'),
|
|
('chat_message', 'Chat Message'),
|
|
('promotion', 'Promotion'),
|
|
('system', 'System'),
|
|
]
|
|
|
|
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
|
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='push_notifications')
|
|
device = models.ForeignKey(MobileDevice, on_delete=models.CASCADE, related_name='notifications')
|
|
notification_type = models.CharField(max_length=20, choices=NOTIFICATION_TYPE_CHOICES)
|
|
title = models.CharField(max_length=200)
|
|
message = models.TextField()
|
|
data = models.JSONField(default=dict) # Additional data for deep linking
|
|
sent_at = models.DateTimeField(auto_now_add=True)
|
|
delivered_at = models.DateTimeField(null=True, blank=True)
|
|
opened_at = models.DateTimeField(null=True, blank=True)
|
|
is_sent = models.BooleanField(default=False)
|
|
is_delivered = models.BooleanField(default=False)
|
|
is_opened = models.BooleanField(default=False)
|
|
|
|
class Meta:
|
|
ordering = ['-sent_at']
|
|
verbose_name = 'Push Notification'
|
|
verbose_name_plural = 'Push Notifications'
|
|
|
|
def __str__(self):
|
|
return f"{self.notification_type}: {self.title}"
|
|
|
|
|
|
class OfflineSync(models.Model):
|
|
"""Offline Sync Tracking für Mobile App"""
|
|
|
|
SYNC_STATUS_CHOICES = [
|
|
('pending', 'Pending'),
|
|
('syncing', 'Syncing'),
|
|
('completed', 'Completed'),
|
|
('failed', 'Failed'),
|
|
]
|
|
|
|
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
|
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='offline_syncs')
|
|
device = models.ForeignKey(MobileDevice, on_delete=models.CASCADE, related_name='syncs')
|
|
sync_type = models.CharField(max_length=50) # 'orders', 'products', 'auctions'
|
|
data = models.JSONField() # Data to sync
|
|
status = models.CharField(max_length=20, choices=SYNC_STATUS_CHOICES, default='pending')
|
|
error_message = models.TextField(blank=True)
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|
synced_at = models.DateTimeField(null=True, blank=True)
|
|
|
|
class Meta:
|
|
ordering = ['-created_at']
|
|
verbose_name = 'Offline Sync'
|
|
verbose_name_plural = 'Offline Syncs'
|
|
|
|
def __str__(self):
|
|
return f"{self.user.username} - {self.sync_type} ({self.get_status_display()})"
|
|
|
|
|
|
class MobileAnalytics(models.Model):
|
|
"""Mobile App Analytics"""
|
|
|
|
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
|
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='mobile_analytics')
|
|
device = models.ForeignKey(MobileDevice, on_delete=models.CASCADE, related_name='analytics')
|
|
event_type = models.CharField(max_length=50) # 'app_open', 'product_view', 'purchase'
|
|
event_data = models.JSONField(default=dict)
|
|
session_id = models.CharField(max_length=100, blank=True)
|
|
screen_name = models.CharField(max_length=100, blank=True)
|
|
timestamp = models.DateTimeField(auto_now_add=True)
|
|
|
|
class Meta:
|
|
ordering = ['-timestamp']
|
|
verbose_name = 'Mobile Analytics'
|
|
verbose_name_plural = 'Mobile Analytics'
|
|
|
|
def __str__(self):
|
|
return f"{self.user.username} - {self.event_type}"
|
|
|
|
|
|
class MobileCache(models.Model):
|
|
"""Mobile App Cache für Offline Support"""
|
|
|
|
CACHE_TYPE_CHOICES = [
|
|
('products', 'Products'),
|
|
('categories', 'Categories'),
|
|
('auctions', 'Auctions'),
|
|
('user_data', 'User Data'),
|
|
]
|
|
|
|
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
|
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='mobile_caches')
|
|
cache_type = models.CharField(max_length=20, choices=CACHE_TYPE_CHOICES)
|
|
cache_key = models.CharField(max_length=255)
|
|
cache_data = models.JSONField()
|
|
expires_at = models.DateTimeField()
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|
updated_at = models.DateTimeField(auto_now=True)
|
|
|
|
class Meta:
|
|
ordering = ['-updated_at']
|
|
verbose_name = 'Mobile Cache'
|
|
verbose_name_plural = 'Mobile Caches'
|
|
unique_together = ['user', 'cache_type', 'cache_key']
|
|
|
|
def __str__(self):
|
|
return f"{self.user.username} - {self.cache_type}: {self.cache_key}"
|
|
|
|
@property
|
|
def is_expired(self):
|
|
"""Prüfen ob Cache abgelaufen ist"""
|
|
return timezone.now() > self.expires_at
|
|
|
|
|
|
class MobileSession(models.Model):
|
|
"""Mobile App Session Tracking"""
|
|
|
|
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
|
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='mobile_sessions')
|
|
device = models.ForeignKey(MobileDevice, on_delete=models.CASCADE, related_name='sessions')
|
|
session_id = models.CharField(max_length=100, unique=True)
|
|
started_at = models.DateTimeField(auto_now_add=True)
|
|
ended_at = models.DateTimeField(null=True, blank=True)
|
|
duration = models.IntegerField(default=0) # in seconds
|
|
is_active = models.BooleanField(default=True)
|
|
|
|
class Meta:
|
|
ordering = ['-started_at']
|
|
verbose_name = 'Mobile Session'
|
|
verbose_name_plural = 'Mobile Sessions'
|
|
|
|
def __str__(self):
|
|
return f"{self.user.username} - {self.session_id}"
|
|
|
|
def end_session(self):
|
|
"""Session beenden"""
|
|
self.ended_at = timezone.now()
|
|
self.is_active = False
|
|
self.duration = int((self.ended_at - self.started_at).total_seconds())
|
|
self.save()
|
|
|
|
|
|
class MobileError(models.Model):
|
|
"""Mobile App Error Tracking"""
|
|
|
|
ERROR_LEVEL_CHOICES = [
|
|
('debug', 'Debug'),
|
|
('info', 'Info'),
|
|
('warning', 'Warning'),
|
|
('error', 'Error'),
|
|
('critical', 'Critical'),
|
|
]
|
|
|
|
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
|
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='mobile_errors')
|
|
device = models.ForeignKey(MobileDevice, on_delete=models.CASCADE, related_name='errors')
|
|
error_level = models.CharField(max_length=20, choices=ERROR_LEVEL_CHOICES)
|
|
error_type = models.CharField(max_length=100)
|
|
error_message = models.TextField()
|
|
stack_trace = models.TextField(blank=True)
|
|
app_version = models.CharField(max_length=20, blank=True)
|
|
os_version = models.CharField(max_length=50, blank=True)
|
|
device_info = models.JSONField(default=dict)
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|
is_resolved = models.BooleanField(default=False)
|
|
|
|
class Meta:
|
|
ordering = ['-created_at']
|
|
verbose_name = 'Mobile Error'
|
|
verbose_name_plural = 'Mobile Errors'
|
|
|
|
def __str__(self):
|
|
return f"{self.error_type}: {self.error_message[:50]}" |