models.py 4.39 KB
Newer Older
1
from django.core.exceptions import ValidationError
2
from django.db import models
3
from django.db.models import Q
4
5
6
7
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _

import events
8
import members
9
from utils.translation import ModelTranslateMeta, MultilingualField
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24


class PizzaEvent(models.Model):
    start = models.DateTimeField(_("Order from"))
    end = models.DateTimeField(_("Order until"))
    event = models.OneToOneField(events.models.Event, on_delete=models.CASCADE)

    @property
    def title(self):
        return self.event.title

    @property
    def in_the_future(self):
        return self.start > timezone.now()

25
26
27
28
    @property
    def has_ended(self):
        return self.end < timezone.now()

29
30
    @property
    def just_ended(self):
31
32
        return (self.has_ended and
                self.end + timezone.timedelta(hours=8) > timezone.now())
33
34
35

    @classmethod
    def current(cls):
36
37
38
39
40
        """
        Get the currently relevant pizza event: the first one
        that starts within 8 hours from now.
        """

41
        try:
42
            events = PizzaEvent.objects.filter(
43
                end__gt=timezone.now() - timezone.timedelta(hours=8),
44
45
46
47
48
49
                start__lte=timezone.now() + timezone.timedelta(hours=8),
            ).order_by('start')
            if events.count() > 1:
                return events.exclude(end__lt=timezone.now()).first()
            else:
                return events.get()
50
51
52
        except PizzaEvent.DoesNotExist:
            return None

53
54
55
56
57
58
59
60
61
62
63
64
65
66
    def validate_unique(self, exclude=None):
        super().validate_unique(exclude)
        for other in PizzaEvent.objects.filter(
                Q(end__gte=self.start, end__lte=self.end) |
                Q(start=self.start, start__lte=self.start)):
            if other.pk == self.pk:
                continue
            raise ValidationError({
                'start': _(
                    'This event cannot overlap with {}.').format(other),
                'end': _(
                    'This event cannot overlap with {}.').format(other),
            })

67
    def clean(self):
68
69
70
71
72
        if self.start >= self.end:
            raise ValidationError({
                'start': _('The start is after the end of this event.'),
                'end': _('The end is before the start of this event.'),
            })
73
74
75
76
77

    def __str__(self):
        return 'Pizzas for ' + str(self.event)


Thom Wiggers's avatar
Thom Wiggers committed
78
79
80
81
82
83
84
class AvailableProductManager(models.Manager):
    """Only shows available products"""

    def get_queryset(self):
        return super().get_queryset().filter(available=True)


85
class Product(models.Model, metaclass=ModelTranslateMeta):
Thom Wiggers's avatar
Thom Wiggers committed
86
87
88
    objects = models.Manager()
    available_products = AvailableProductManager()

89
90
91
92
    name = models.CharField(max_length=50)
    description = MultilingualField(models.TextField)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    available = models.BooleanField(default=True)
Thom Wiggers's avatar
Thom Wiggers committed
93
94
95
96
    restricted = models.BooleanField(
        default=False,
        help_text=_("Only allow to be ordered by people with the "
                    "'order restricted products' permission."))
97
98
99
100

    def __str__(self):
        return self.name

101
102
    class Meta:
        ordering = ('name', )
103
104
105
        permissions = (
            ('order_restricted_products', _('Order restricted products')),
        )
106

107
108
109

class Order(models.Model):
    member = models.ForeignKey(
110
        members.models.Member,
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
        on_delete=models.CASCADE,
        blank=True,
        null=True,
    )

    paid = models.BooleanField(default=False)

    name = models.CharField(
        max_length=50,
        help_text=_('Use this for non-members'),
        null=True,
        blank=True,
    )

    product = models.ForeignKey(Product, on_delete=models.PROTECT)
    pizza_event = models.ForeignKey(PizzaEvent, on_delete=models.CASCADE)

    def clean(self):
        if ((self.member is None and not self.name) or
                (self.member and self.name)):
            raise ValidationError({
                'member': _('Either specify a member or a name'),
                'name': _('Either specify a member or a name'),
            })

    @property
    def member_name(self):
        if self.member is not None:
            return self.member.get_full_name()
        return self.name

142
143
144
145
    @property
    def can_be_changed(self):
        return not self.paid and not self.pizza_event.has_ended

146
    class Meta:
147
        unique_together = ('pizza_event', 'member',)