first commit
This commit is contained in:
167
monitor/models.py
Normal file
167
monitor/models.py
Normal file
@@ -0,0 +1,167 @@
|
||||
from django.db import models
|
||||
from django.core.validators import MinValueValidator, MaxValueValidator
|
||||
from decimal import Decimal
|
||||
|
||||
class BitcoinPrice(models.Model):
|
||||
"""
|
||||
Stores historical Bitcoin price data.
|
||||
"""
|
||||
timestamp = models.DateTimeField(auto_now_add=True)
|
||||
price_usd = models.DecimalField(max_digits=20, decimal_places=2)
|
||||
volume = models.DecimalField(max_digits=30, decimal_places=2, null=True, blank=True)
|
||||
market_cap = models.DecimalField(max_digits=30, decimal_places=2, null=True, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return f"Bitcoin: ${self.price_usd} at {self.timestamp.strftime('%Y-%m-%d %H:%M')}"
|
||||
|
||||
class Meta:
|
||||
ordering = ['-timestamp'] # Newest first
|
||||
|
||||
|
||||
|
||||
class MarketAnalysis(models.Model):
|
||||
"""
|
||||
Stores market analysis results.
|
||||
"""
|
||||
STATUS_CHOICES = [
|
||||
('dip', 'Dip'),
|
||||
('peak', 'Peak'),
|
||||
('neutral', 'Neutral'),
|
||||
]
|
||||
|
||||
timestamp = models.DateTimeField(auto_now_add=True)
|
||||
period = models.CharField(max_length=10, choices=[
|
||||
('hourly', 'Hourly'),
|
||||
('daily', 'Daily'),
|
||||
('weekly', 'Weekly'),
|
||||
('yearly', 'Yearly'),
|
||||
], default='hourly')
|
||||
|
||||
# Price statistics
|
||||
current_price = models.DecimalField(max_digits=20, decimal_places=2)
|
||||
average_price = models.DecimalField(max_digits=20, decimal_places=2)
|
||||
min_price = models.DecimalField(max_digits=20, decimal_places=2)
|
||||
max_price = models.DecimalField(max_digits=20, decimal_places=2)
|
||||
|
||||
# Analysis results
|
||||
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='neutral')
|
||||
threshold_percent = models.DecimalField(
|
||||
max_digits=5,
|
||||
decimal_places=2,
|
||||
default=15.0,
|
||||
validators=[MinValueValidator(Decimal('0.01')), MaxValueValidator(Decimal('100'))]
|
||||
)
|
||||
|
||||
# Calculated thresholds
|
||||
lower_threshold = models.DecimalField(max_digits=20, decimal_places=2)
|
||||
upper_threshold = models.DecimalField(max_digits=20, decimal_places=2)
|
||||
|
||||
# Event tracking
|
||||
is_event = models.BooleanField(default=False)
|
||||
event_type = models.CharField(max_length=20, blank=True, choices=[
|
||||
('dip_below', 'Dip Below Threshold'),
|
||||
('rise_above', 'Rise Above Threshold'),
|
||||
('neutralized', 'Neutralized'),
|
||||
])
|
||||
|
||||
def __str__(self):
|
||||
return f"Analysis: {self.status.upper()} at ${self.current_price}"
|
||||
|
||||
class Meta:
|
||||
ordering = ['-timestamp']
|
||||
verbose_name_plural = "Market Analyses"
|
||||
|
||||
class SystemStatus(models.Model):
|
||||
"""
|
||||
Tracks system health and status for monitoring.
|
||||
"""
|
||||
timestamp = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
# Update status
|
||||
last_hourly_update = models.DateTimeField(null=True, blank=True)
|
||||
last_successful_fetch = models.DateTimeField(null=True, blank=True)
|
||||
|
||||
# Current status
|
||||
current_price = models.DecimalField(
|
||||
max_digits=20, decimal_places=2, null=True, blank=True
|
||||
)
|
||||
|
||||
# Error tracking
|
||||
last_error = models.TextField(blank=True)
|
||||
is_stale = models.BooleanField(default=True)
|
||||
is_healthy = models.BooleanField(default=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ['-timestamp']
|
||||
verbose_name_plural = "System Statuses"
|
||||
|
||||
def __str__(self):
|
||||
status = "Healthy" if self.is_healthy else "Unhealthy"
|
||||
return f"System Status: {status} at {self.timestamp}"
|
||||
|
||||
class NotificationPreference(models.Model):
|
||||
"""
|
||||
Stores notification preferences for each email address.
|
||||
"""
|
||||
email_address = models.EmailField(unique=True)
|
||||
receive_event_alerts = models.BooleanField(
|
||||
default=True,
|
||||
help_text="Receive immediate alerts for threshold events"
|
||||
)
|
||||
receive_system_alerts = models.BooleanField(
|
||||
default=True,
|
||||
help_text="Receive alerts for system failures and issues"
|
||||
)
|
||||
receive_daily_digest = models.BooleanField(
|
||||
default=True,
|
||||
help_text="Receive daily summary email at 8 AM"
|
||||
)
|
||||
is_active = models.BooleanField(default=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.email_address} (Active: {self.is_active})"
|
||||
|
||||
class Meta:
|
||||
ordering = ['-created_at']
|
||||
|
||||
|
||||
class EmailNotification(models.Model):
|
||||
"""
|
||||
Records of all emails sent by the system.
|
||||
"""
|
||||
NOTIFICATION_TYPES = [
|
||||
('event', 'Event Alert'),
|
||||
('system', 'System Alert'),
|
||||
('digest', 'Daily Digest'),
|
||||
('test', 'Test Email'),
|
||||
]
|
||||
|
||||
STATUS_CHOICES = [
|
||||
('pending', 'Pending'),
|
||||
('sent', 'Sent'),
|
||||
('failed', 'Failed'),
|
||||
('retrying', 'Retrying'),
|
||||
]
|
||||
|
||||
recipient = models.EmailField()
|
||||
subject = models.CharField(max_length=255)
|
||||
notification_type = models.CharField(max_length=20, choices=NOTIFICATION_TYPES)
|
||||
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending')
|
||||
content_html = models.TextField(blank=True)
|
||||
content_text = models.TextField(blank=True)
|
||||
error_message = models.TextField(blank=True)
|
||||
sent_at = models.DateTimeField(null=True, blank=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
retry_count = models.IntegerField(default=0)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.notification_type} to {self.recipient} - {self.status}"
|
||||
|
||||
class Meta:
|
||||
ordering = ['-created_at']
|
||||
indexes = [
|
||||
models.Index(fields=['recipient', 'created_at']),
|
||||
models.Index(fields=['notification_type', 'status']),
|
||||
]
|
||||
Reference in New Issue
Block a user