models.py 8.91 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

from core.models import User

Skia's avatar
Skia committed
11
12
13
import MySQLdb


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

def validate_payment(value):
19
    if value not in settings.SITH_SUBSCRIPTION_PAYMENT_METHOD:
20
21
        raise ValidationError(_('Bad payment method'))

22
23
24
class Subscriber(User):
    class Meta:
        proxy = True
25
26

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

Skia's avatar
Skia committed
30
31
32
33
34
35
36
37
38
39
40
41
42
    def save(self):
        super(Subscriber, self).save()
        try:
            db = MySQLdb.connect(**settings.OLD_MYSQL_INFOS)
            c = db.cursor()
            c.execute("""INSERT INTO utilisateurs (nom_utl, prenom_utl, email_utl, hash_utl) VALUES
            (%s, %s, %s, %s)""", (self.last_name, self.first_name, self.email, "valid", ))
        except Exception as e:
            with open("/home/sith/user_fail.log", "a") as f:
                print("FAIL to add user %s (%s %s - %s) to old site" % (self.id, self.first_name, self.last_name,
                    self.email), file=f)
                print("Reason: %s" % (repr(e)), file=f)

43
class Subscription(models.Model):
44
    member = models.ForeignKey(Subscriber, related_name='subscriptions')
45
46
    subscription_type = models.CharField(_('subscription type'),
                                         max_length=255,
Skia's avatar
Skia committed
47
                                         choices=((k, v['name']) for k,v in sorted(settings.SITH_SUBSCRIPTIONS.items())))
48
49
    subscription_start = models.DateField(_('subscription start'))
    subscription_end = models.DateField(_('subscription end'))
50
    payment_method = models.CharField(_('payment method'), max_length=255, choices=settings.SITH_SUBSCRIPTION_PAYMENT_METHOD)
Skia's avatar
Skia committed
51
52
    location = models.CharField(choices=settings.SITH_SUBSCRIPTION_LOCATIONS,
            max_length=20, verbose_name=_('location'))
53

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

    def clean(self):
58
59
60
61
62
63
64
65
        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"))
66

67
68
69
70
    def save(self):
        super(Subscription, self).save()
        from counter.models import Customer
        if not Customer.objects.filter(user=self.member).exists():
Skia's avatar
Skia committed
71
72
            last_id = Customer.objects.count() + 5195 # Number to keep a continuity with the old site
            Customer(user=self.member, account_id=Customer.generate_account_id(last_id+1), amount=0).save()
Skia's avatar
Skia committed
73
        self.member.make_home()
Skia's avatar
Skia committed
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
        try:
            LOCATION = {
                    "SEVENANS": 5,
                    "BELFORT": 6,
                    "MONTBELIARD": 9,
                    }
            TYPE = {
                    'un-semestre'                 : 0,
                    'deux-semestres'              : 1,
                    'cursus-tronc-commun'         : 2,
                    'cursus-branche'              : 3,
                    'membre-honoraire'            : 4,
                    'assidu'                      : 5,
                    'amicale/doceo'               : 6,
                    'reseau-ut'                   : 7,
                    'crous'                       : 8,
                    'sbarro/esta'                 : 9,
                    'cursus-alternant'           : 10,
                    }
            PAYMENT = {
                    "CHECK"           :  1,
                    "CARD"            :  2,
                    "CASH"            :  3,
                    "OTHER"           :  4,
                    "EBOUTIC"         :  5,
                    "OTHER"           :  0,
                    }

            db = MySQLdb.connect(**settings.OLD_MYSQL_INFOS)
            c = db.cursor()
            c.execute("""INSERT INTO ae_cotisations (id_utilisateur, date_cotis, date_fin_cotis, mode_paiement_cotis,
            type_cotis, id_comptoir) VALUES (%s, %s, %s, %s, %s, %s)""", (self.member.id, self.subscription_start,
                self.subscription_end, PAYMENT[self.payment_method], TYPE[self.subscription_type],
                LOCATION[self.location]))
        except Exception as e:
            with open("/home/sith/subscription_fail.log", "a") as f:
                print("FAIL to add subscription to %s to old site" % (self.member), file=f)
                print("Reason: %s" % (repr(e)), file=f)
112

113
    def get_absolute_url(self):
114
        return reverse('core:user_edit', kwargs={'user_id': self.member.pk})
115

116
    def __str__(self):
117
118
119
120
121
        if hasattr(self, "member") and self.member is not None:
            return self.member.username+' - '+str(self.pk)
        else:
            return 'No user - '+str(self.pk)

122

123
    @staticmethod
124
    def compute_start(d=date.today(), duration=1):
125
126
        """
        This function computes the start date of the subscription with respect to the given date (default is today),
Skia's avatar
Skia committed
127
        and the start date given in settings.SITH_START_DATE.
128
        It takes the nearest past start date.
Skia's avatar
Skia committed
129
        Exemples: with SITH_START_DATE = (8, 15)
130
131
132
133
            Today      -> Start date
            2015-03-17 -> 2015-02-15
            2015-01-11 -> 2014-08-15
        """
134
135
        if duration <= 2: # Sliding subscriptions for 1 or 2 semesters
            return d
136
137
        today = d
        year = today.year
Skia's avatar
Skia committed
138
        start = date(year, settings.SITH_START_DATE[0], settings.SITH_START_DATE[1])
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
        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:
161
            start = Subscription.compute_start(duration=duration)
162
        # This can certainly be simplified, but it works like this
163
164
165
166
167
        try:
            return start.replace(month=(start.month-1+6*duration)%12+1,
                             year=start.year+int(duration/2)+(1 if start.month > 6 and duration%2 == 1 else 0))
        except ValueError as e:
            return start.replace(day=1, month=(start.month+6*duration)%12+1,
168
169
                             year=start.year+int(duration/2)+(1 if start.month > 6 and duration%2 == 1 else 0))

170

Skia's avatar
Skia committed
171
    def can_be_edited_by(self, user):
Skia's avatar
Skia committed
172
        return user.is_in_group(settings.SITH_MAIN_BOARD_GROUP) or user.is_root
Skia's avatar
Skia committed
173

174
175
176
    def is_valid_now(self):
        return self.subscription_start <= date.today() and date.today() <= self.subscription_end

177
178
179
180
def guy_test(date, duration=4):
    print(str(date)+" - "+str(duration)+" -> "+str(Subscription.compute_start(date, duration)))
def bibou_test(duration, date=date.today()):
    print(str(date)+" - "+str(duration)+" -> "+str(Subscription.compute_end(duration, Subscription.compute_start(date, duration))))
181
182
183
184
185
186
187
188
189
190
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)
191
192
193
194
195
196
197
198
199
    guy_test(date(2015, 7, 11), 1)
    guy_test(date(2015, 8, 11), 2)
    guy_test(date(2015, 2, 17), 3)
    guy_test(date(2015, 3, 17), 4)
    guy_test(date(2015, 1, 11), 1)
    guy_test(date(2015, 2, 11), 2)
    guy_test(date(2015, 8, 17), 3)
    guy_test(date(2015, 9, 17), 4)
    print('='*80)
200
201
202
203
204
205
206
207
    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))
208
    print('='*80)
Skia's avatar
Skia committed
209
    bibou_test(1, date(2000, 2, 29))
210
211
212
    bibou_test(2, date(2000, 2, 29))
    bibou_test(1, date(2000, 5, 31))
    bibou_test(1, date(2000, 7, 31))
213
214
215
216
217
218
219
    bibou_test(1)
    bibou_test(2)
    bibou_test(3)
    bibou_test(4)

if __name__ == "__main__":
    guy()