models.py 4.79 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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

from core.models import User

def validate_type(value):
    if value not in settings.AE_SUBSCRIPTIONS.keys():
        raise ValidationError(_('Bad subscription type'))

def validate_payment(value):
    if value not in settings.AE_PAYMENT_METHOD:
        raise ValidationError(_('Bad payment method'))

class Member(models.Model):
    user = models.OneToOneField(User, primary_key=True)

    def is_subscribed(self):
        return self.subscriptions.last().is_valid_now()

23
24
25
    def __str__(self):
        return self.user.username

26
27
28
29
class Subscription(models.Model):
    member = models.ForeignKey(Member, related_name='subscriptions')
    subscription_type = models.CharField(_('subscription type'),
                                         max_length=255,
30
                                         choices=((k, v['name']) for k,v in sorted(settings.AE_SUBSCRIPTIONS.items())))
31
32
33
34
    subscription_start = models.DateField(_('subscription start'))
    subscription_end = models.DateField(_('subscription end'))
    payment_method = models.CharField(_('payment method'), max_length=255, choices=settings.AE_PAYMENT_METHOD)

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
    def save(self, *args, **kwargs):
        """
        This makes the Subscription to be updated with right dates with respect to date.today() each time you save the
        Subscription object.
        It means that you must be careful when modifying old Subscription, because you could make
        someone that had no more valid subscription to get one again!

        TODO: FIXME by putting it in the right function that would be triggered only when using the right Form!!!!
        """
        self.subscription_start = self.compute_start()
        self.subscription_end = self.compute_end(
                duration=settings.AE_SUBSCRIPTIONS[self.subscription_type]['duration'],
                start=self.subscription_start)
        super(Subscription, self).save(*args, **kwargs)

50
51
52
    class Meta:
        ordering = ['subscription_start',]

53
54
55
    def __str__(self):
        return self.member.user.username+' - '+str(self.pk)

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
    @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),
        and the start date given in settings.AE_START_DATE.
        It takes the nearest past start date.
        Exemples: with AE_START_DATE = (8, 15)
            Today      -> Start date
            2015-03-17 -> 2015-02-15
            2015-01-11 -> 2014-08-15
        """
        today = d
        year = today.year
        start = date(year, settings.AE_START_DATE[0], settings.AE_START_DATE[1])
        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))

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