Coverage for website/promotion/models.py: 61.43%
60 statements
« prev ^ index » next coverage.py v7.6.7, created at 2025-08-14 10:31 +0000
« prev ^ index » next coverage.py v7.6.7, created at 2025-08-14 10:31 +0000
1"""Models for the promotion requests database tables."""
3from django.db import models
4from django.dispatch import Signal
5from django.utils import timezone
6from django.utils.translation import gettext_lazy as _
8from tinymce.models import HTMLField
10from events.models import Event
12updated_status = Signal()
15class PromotionChannel(models.Model):
16 name = models.CharField(verbose_name=_("Channel name"), max_length=100)
17 publisher_reminder_email = models.EmailField(
18 verbose_name="Publisher Reminder Email",
19 blank=True,
20 null=True,
21 )
22 publish_deadline = models.DurationField(
23 verbose_name="Minimum time between request and publish",
24 default=timezone.timedelta(weeks=2),
25 )
27 def __str__(self):
28 return str(self.name)
31class UpcomingRequestManager(models.Manager):
32 def get_queryset(self):
33 end_date = timezone.localdate()
34 start_date = end_date - timezone.timedelta(weeks=1)
35 return super().get_queryset().filter(created_at__range=(start_date, end_date))
38class NewRequestManager(models.Manager):
39 def get_queryset(self):
40 start_date = timezone.localtime()
41 end_date = start_date + timezone.timedelta(weeks=1)
42 return super().get_queryset().filter(publish_date__range=(start_date, end_date))
45class PromotionRequest(models.Model):
46 objects = models.Manager()
47 upcoming_requests = UpcomingRequestManager()
48 new_requests = NewRequestManager()
50 created_at = models.DateTimeField(
51 verbose_name=_("created at"), auto_now_add=True, null=False, blank=False
52 )
53 event = models.ForeignKey(
54 Event, verbose_name=_("event"), on_delete=models.CASCADE, null=True, blank=True
55 )
56 publish_date = models.DateField(
57 verbose_name=_("Publish date"),
58 null=False,
59 blank=False,
60 )
61 channel = models.ForeignKey(
62 PromotionChannel,
63 verbose_name=_("channel"),
64 on_delete=models.CASCADE,
65 null=False,
66 blank=False,
67 )
68 assigned_to = models.CharField(
69 null=True,
70 blank=True,
71 max_length=50,
72 verbose_name=_("Assigned to"),
73 )
75 NOT_STARTED = "not_started"
76 STARTED = "started"
77 FINISHED = "finished"
78 PUBLISHED = "published"
80 STATUS_TYPES = (
81 (NOT_STARTED, _("Not started")),
82 (STARTED, _("Started")),
83 (FINISHED, _("Finished")),
84 (PUBLISHED, _("Published")),
85 )
87 status = models.CharField(
88 max_length=40,
89 choices=STATUS_TYPES,
90 verbose_name=_("status"),
91 default=NOT_STARTED,
92 null=False,
93 blank=False,
94 )
95 drive_folder = models.URLField(
96 verbose_name=_("drive folder"),
97 null=True,
98 blank=True,
99 max_length=2000, # This appears to be the max allowed url length
100 )
101 remarks = HTMLField(
102 verbose_name=_("remarks"),
103 null=True,
104 blank=True,
105 )
106 status_updated = models.BooleanField(
107 verbose_name=_("status updated"),
108 default=False,
109 )
111 def __str__(self):
112 if self.event: 112 ↛ 113line 112 didn't jump to line 113 because the condition on line 112 was never true
113 return _("Promotion request for ") + str(self.event)
114 return _("Promotion request ") + str(self.pk)
116 def save(self, **kwargs):
117 if not self.publish_date and self.event:
118 self.publish_date = self.event.start.date()
119 oldstatus = None
120 if self.pk:
121 oldstatus = PromotionRequest.objects.get(pk=self.pk).status
122 if not self.status_updated:
123 self.status_updated = oldstatus != self.status
124 ret = super().save(**kwargs)
125 if oldstatus and oldstatus != self.status:
126 updated_status.send(sender=None, updated_request=self)
127 return ret
129 class Meta:
130 verbose_name = _("Promotion request")
131 verbose_name_plural = _("Promotion requests")