models.py 9.55 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
Skia's avatar
Skia committed
8
from django.contrib.auth.forms import PasswordResetForm
9 10 11

from core.models import User

Skia's avatar
Skia committed
12 13 14
import MySQLdb


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

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

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

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

Skia's avatar
Skia committed
31 32
    def save(self):
        super(Subscriber, self).save()
33
        try: # Create user on the old site: TODO remove me!
Skia's avatar
Skia committed
34 35
            db = MySQLdb.connect(**settings.OLD_MYSQL_INFOS)
            c = db.cursor()
36 37 38
            c.execute("""INSERT INTO utilisateurs (id_utilisateur, nom_utl, prenom_utl, email_utl, hash_utl, ae_utl) VALUES
            (%s, %s, %s, %s, %s, %s)""", (self.id, self.last_name, self.first_name, self.email, "valid", "1"))
            db.commit()
Skia's avatar
Skia committed
39
        except Exception as e:
40
            with open(settings.BASE_DIR+"/user_fail.log", "a") as f:
Skia's avatar
Skia committed
41 42 43
                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)
44
            db.rollback()
Skia's avatar
Skia committed
45

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

57
    class Meta:
58
        ordering = ['subscription_start',]
59 60

    def clean(self):
61 62 63 64 65 66 67 68
        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"))
69

70 71 72 73
    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
74
            last_id = Customer.objects.count() + 1504 # Number to keep a continuity with the old site
Skia's avatar
Skia committed
75
            Customer(user=self.member, account_id=Customer.generate_account_id(last_id+1), amount=0).save()
Skia's avatar
Skia committed
76 77 78 79
            form = PasswordResetForm({'email': self.member.email})
            if form.is_valid():
                form.save(use_https=True, email_template_name='core/new_user_email.jinja',
                        subject_template_name='core/new_user_email_subject.jinja', from_email="ae@utbm.fr")
Skia's avatar
Skia committed
80
        self.member.make_home()
81
        try: # Create subscription on the old site: TODO remove me!
Skia's avatar
Skia committed
82 83 84 85
            LOCATION = {
                    "SEVENANS": 5,
                    "BELFORT": 6,
                    "MONTBELIARD": 9,
Skia's avatar
Skia committed
86
                    "EBOUTIC": 5,
Skia's avatar
Skia committed
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
                    }
            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]))
116
            db.commit()
Skia's avatar
Skia committed
117
        except Exception as e:
118
            with open(settings.BASE_DIR+"/subscription_fail.log", "a") as f:
Skia's avatar
Skia committed
119 120
                print("FAIL to add subscription to %s to old site" % (self.member), file=f)
                print("Reason: %s" % (repr(e)), file=f)
121
            db.rollback()
122

123
    def get_absolute_url(self):
124
        return reverse('core:user_edit', kwargs={'user_id': self.member.pk})
125

126
    def __str__(self):
127 128 129 130 131
        if hasattr(self, "member") and self.member is not None:
            return self.member.username+' - '+str(self.pk)
        else:
            return 'No user - '+str(self.pk)

132

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

180

Skia's avatar
Skia committed
181
    def can_be_edited_by(self, user):
Skia's avatar
Skia committed
182
        return user.is_in_group(settings.SITH_MAIN_BOARD_GROUP) or user.is_root
Skia's avatar
Skia committed
183

184 185 186
    def is_valid_now(self):
        return self.subscription_start <= date.today() and date.today() <= self.subscription_end

187 188 189 190
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))))
191 192 193 194 195 196 197 198 199 200
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)
201 202 203 204 205 206 207 208 209
    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)
210 211 212 213 214 215 216 217
    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))
218
    print('='*80)
Skia's avatar
Skia committed
219
    bibou_test(1, date(2000, 2, 29))
220 221 222
    bibou_test(2, date(2000, 2, 29))
    bibou_test(1, date(2000, 5, 31))
    bibou_test(1, date(2000, 7, 31))
223 224 225 226 227 228 229
    bibou_test(1)
    bibou_test(2)
    bibou_test(3)
    bibou_test(4)

if __name__ == "__main__":
    guy()