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

1"""Models for the promotion requests database tables.""" 

2 

3from django.db import models 

4from django.dispatch import Signal 

5from django.utils import timezone 

6from django.utils.translation import gettext_lazy as _ 

7 

8from tinymce.models import HTMLField 

9 

10from events.models import Event 

11 

12updated_status = Signal() 

13 

14 

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 ) 

26 

27 def __str__(self): 

28 return str(self.name) 

29 

30 

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)) 

36 

37 

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)) 

43 

44 

45class PromotionRequest(models.Model): 

46 objects = models.Manager() 

47 upcoming_requests = UpcomingRequestManager() 

48 new_requests = NewRequestManager() 

49 

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 ) 

74 

75 NOT_STARTED = "not_started" 

76 STARTED = "started" 

77 FINISHED = "finished" 

78 PUBLISHED = "published" 

79 

80 STATUS_TYPES = ( 

81 (NOT_STARTED, _("Not started")), 

82 (STARTED, _("Started")), 

83 (FINISHED, _("Finished")), 

84 (PUBLISHED, _("Published")), 

85 ) 

86 

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 ) 

110 

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) 

115 

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 

128 

129 class Meta: 

130 verbose_name = _("Promotion request") 

131 verbose_name_plural = _("Promotion requests")