models.py 5.31 KB
Newer Older
1
2
3
4
5
from datetime import date, timedelta
from django.db import models
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
6
7
from django.core.exceptions import ValidationError
from django.core.urlresolvers import reverse
8
9
10
11

from core.models import User

def validate_type(value):
Skia's avatar
Skia committed
12
    if value not in settings.SITH_SUBSCRIPTIONS.keys():
13
14
15
        raise ValidationError(_('Bad subscription type'))

def validate_payment(value):
16
    if value not in settings.SITH_SUBSCRIPTION_PAYMENT_METHOD:
17
18
        raise ValidationError(_('Bad payment method'))

19
20
21
class Subscriber(User):
    class Meta:
        proxy = True
22
23

    def is_subscribed(self):
Skia's avatar
Skia committed
24
25
        s = self.subscriptions.last()
        return s.is_valid_now() if s is not None else False
26
27

class Subscription(models.Model):
28
    member = models.ForeignKey(Subscriber, related_name='subscriptions')
29
30
    subscription_type = models.CharField(_('subscription type'),
                                         max_length=255,
Skia's avatar
Skia committed
31
                                         choices=((k, v['name']) for k,v in sorted(settings.SITH_SUBSCRIPTIONS.items())))
32
33
    subscription_start = models.DateField(_('subscription start'))
    subscription_end = models.DateField(_('subscription end'))
34
    payment_method = models.CharField(_('payment method'), max_length=255, choices=settings.SITH_SUBSCRIPTION_PAYMENT_METHOD)
Skia's avatar
Skia committed
35
    # TODO add location!
36

37
38
39
40
41
42
43
    class Meta:
        permissions = (
                ('change_subscription', 'Can make someone become a subscriber'),
                ('view_subscription', 'Can view who is a subscriber'),
                )

    def clean(self):
44
45
46
47
48
49
50
51
        try:
            for s in Subscription.objects.filter(member=self.member).exclude(pk=self.pk).all():
                if s.is_valid_now():
                    raise ValidationError(_("You can not subscribe many time for the same period"))
        except: # This should not happen, because the form should have handled the data before, but sadly, it still
                # calls the model validation :'(
                # TODO see SubscriptionForm's clean method
            raise ValidationError(_("You are trying to create a subscription without member"))
52

53
54
55
    class Meta:
        ordering = ['subscription_start',]

56
57
58
    def get_absolute_url(self):
        return reverse('core:user_profile', kwargs={'user_id': self.member.pk})

59
    def __str__(self):
60
61
62
63
64
        if hasattr(self, "member") and self.member is not None:
            return self.member.username+' - '+str(self.pk)
        else:
            return 'No user - '+str(self.pk)

65

66
67
68
69
    @staticmethod
    def compute_start(d=date.today()):
        """
        This function computes the start date of the subscription with respect to the given date (default is today),
Skia's avatar
Skia committed
70
        and the start date given in settings.SITH_START_DATE.
71
        It takes the nearest past start date.
Skia's avatar
Skia committed
72
        Exemples: with SITH_START_DATE = (8, 15)
73
74
75
76
77
78
            Today      -> Start date
            2015-03-17 -> 2015-02-15
            2015-01-11 -> 2014-08-15
        """
        today = d
        year = today.year
Skia's avatar
Skia committed
79
        start = date(year, settings.SITH_START_DATE[0], settings.SITH_START_DATE[1])
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
        start2 = start.replace(month=(start.month+6)%12)
        if start > start2:
            start, start2 = start2, start
        if today < start:
            return start2.replace(year=year-1)
        elif today < start2:
            return start
        else:
            return start2

    @staticmethod
    def compute_end(duration, start=None):
        """
        This function compute the end date of the subscription given a start date and a duration in number of semestre
        Exemple:
            Start - Duration -> End date
            2015-09-18 - 1 -> 2016-03-18
            2015-09-18 - 2 -> 2016-09-18
            2015-09-18 - 3 -> 2017-03-18
            2015-09-18 - 4 -> 2017-09-18
        """
        if start is None:
            start = Subscription.compute_start()
        # This can certainly be simplified, but it works like this
        return start.replace(month=(start.month+6*duration)%12,
                             year=start.year+int(duration/2)+(1 if start.month > 6 and duration%2 == 1 else 0))

Skia's avatar
Skia committed
107
    def can_be_edited_by(self, user):
Skia's avatar
Skia committed
108
        return user.is_in_group(settings.SITH_MAIN_BOARD_GROUP) or user.is_in_group(settings.SITH_GROUPS['root']['name'])
Skia's avatar
Skia committed
109

110
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
    def is_valid_now(self):
        return self.subscription_start <= date.today() and date.today() <= self.subscription_end

def guy_test(date):
    print(str(date)+" -> "+str(Subscription.compute_start(date)))
def bibou_test(duration, date=None):
    print(str(date)+" - "+str(duration)+" -> "+str(Subscription.compute_end(duration, date)))
def guy():
    guy_test(date(2015, 7, 11))
    guy_test(date(2015, 8, 11))
    guy_test(date(2015, 2, 17))
    guy_test(date(2015, 3, 17))
    guy_test(date(2015, 1, 11))
    guy_test(date(2015, 2, 11))
    guy_test(date(2015, 8, 17))
    guy_test(date(2015, 9, 17))
    print('='*80)
    bibou_test(1, date(2015, 2, 18))
    bibou_test(2, date(2015, 2, 18))
    bibou_test(3, date(2015, 2, 18))
    bibou_test(4, date(2015, 2, 18))
    bibou_test(1, date(2015, 9, 18))
    bibou_test(2, date(2015, 9, 18))
    bibou_test(3, date(2015, 9, 18))
    bibou_test(4, date(2015, 9, 18))
    bibou_test(1)
    bibou_test(2)
    bibou_test(3)
    bibou_test(4)

if __name__ == "__main__":
    guy()