diff --git a/mailing/migrations/0002_remove_subscriber_prospect.py b/mailing/migrations/0002_remove_subscriber_prospect.py new file mode 100644 index 0000000..28776c7 --- /dev/null +++ b/mailing/migrations/0002_remove_subscriber_prospect.py @@ -0,0 +1,17 @@ +# Generated by Django 5.1 on 2025-10-08 12:40 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('mailing', '0001_initial'), + ] + + operations = [ + migrations.RemoveField( + model_name='subscriber', + name='prospect', + ), + ] diff --git a/mailing/models.py b/mailing/models.py index fcb547a..bd93135 100644 --- a/mailing/models.py +++ b/mailing/models.py @@ -12,13 +12,13 @@ class MailingList(BaseModel): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=True) name = models.CharField(max_length=100) description = models.TextField(blank=True, null=True) - + def delete_dependencies(self): pass - + def __str__(self): return self.name - + def subscriber_count(self): return self.subscribers.filter(is_active=True).count() @@ -31,22 +31,22 @@ class Subscriber(BaseModel): mailing_lists = models.ManyToManyField(MailingList, related_name='subscribers', blank=True) is_active = models.BooleanField(default=True) unsubscribe_token = models.UUIDField(default=uuid.uuid4, unique=True) - + # Optional reference to actual user models user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True) - prospect = models.ForeignKey('biz.Prospect', on_delete=models.CASCADE, blank=True, null=True) - + # prospect = models.ForeignKey('biz.Prospect', on_delete=models.CASCADE, blank=True, null=True) + class Meta: unique_together = ['email'] - + def delete_dependencies(self): pass - + def __str__(self): if self.first_name and self.last_name: return f"{self.first_name} {self.last_name} ({self.email})" return self.email - + def full_name(self): if self.first_name and self.last_name: return f"{self.first_name} {self.last_name}" @@ -63,10 +63,10 @@ class EmailTemplate(BaseModel): subject = models.CharField(max_length=200) html_content = models.TextField(help_text="HTML content with image support") text_content = models.TextField(blank=True, null=True, help_text="Plain text fallback") - + def delete_dependencies(self): pass - + def __str__(self): return self.name @@ -79,23 +79,23 @@ class Campaign(BaseModel): html_content = models.TextField(blank=True, null=True) text_content = models.TextField(blank=True, null=True) mailing_lists = models.ManyToManyField(MailingList, related_name='campaigns') - + sent_at = models.DateTimeField(blank=True, null=True) is_sent = models.BooleanField(default=False) - + # Email tracking total_sent = models.IntegerField(default=0) total_delivered = models.IntegerField(default=0) total_opened = models.IntegerField(default=0) total_clicked = models.IntegerField(default=0) total_bounced = models.IntegerField(default=0) - + def delete_dependencies(self): pass - + def __str__(self): return self.name - + def get_content(self): if self.template: return { @@ -106,7 +106,7 @@ class Campaign(BaseModel): 'html': self.html_content, 'text': self.text_content } - + def get_subject(self): return self.subject or (self.template.subject if self.template else "") @@ -115,44 +115,44 @@ class EmailLog(BaseModel): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=True) campaign = models.ForeignKey(Campaign, on_delete=models.CASCADE, related_name='email_logs') subscriber = models.ForeignKey(Subscriber, on_delete=models.CASCADE, related_name='email_logs') - + tracking_id = models.UUIDField(default=uuid.uuid4, unique=True) - + # Email status sent_at = models.DateTimeField(blank=True, null=True) delivered_at = models.DateTimeField(blank=True, null=True) opened_at = models.DateTimeField(blank=True, null=True) clicked_at = models.DateTimeField(blank=True, null=True) bounced_at = models.DateTimeField(blank=True, null=True) - + # Error tracking error_message = models.TextField(blank=True, null=True) - + class Meta: unique_together = ['campaign', 'subscriber'] - + def delete_dependencies(self): pass - + def __str__(self): return f"{self.campaign.name} - {self.subscriber.email}" - + @property def is_sent(self): return self.sent_at is not None - + @property def is_delivered(self): return self.delivered_at is not None - + @property def is_opened(self): return self.opened_at is not None - + @property def is_clicked(self): return self.clicked_at is not None - + @property def is_bounced(self): return self.bounced_at is not None