furry/mobile/models.py

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]}"