models.py 9.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
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
    def save(self):
Skia's avatar
Skia committed
32 33 34
        create = False
        if not self.id:
            create = True
Skia's avatar
Skia committed
35
        super(Subscriber, self).save()
Sli's avatar
Sli committed
36
        if create and settings.IS_OLD_MYSQL_PRESENT:
Skia's avatar
Skia committed
37 38 39 40 41 42 43 44 45 46 47 48
            try: # Create user on the old site: TODO remove me!
                db = MySQLdb.connect(**settings.OLD_MYSQL_INFOS)
                c = db.cursor()
                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()
            except Exception as e:
                with open(settings.BASE_DIR+"/user_fail.log", "a") as f:
                    print("FAIL to add user %s (%s %s - %s) to old site" % (self.id, self.first_name.encode('utf-8'),
                        self.last_name.encode('utf-8'), self.email), file=f)
                    print("Reason: %s" % (repr(e)), file=f)
                db.rollback()
Skia's avatar
Skia committed
49

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

61
    class Meta:
62
        ordering = ['subscription_start',]
63 64

    def clean(self):
65 66 67 68 69 70 71
        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
Skia's avatar
Skia committed
72
            raise ValidationError(_("Subscription error"))
73

74 75 76 77
    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
78
            last_id = Customer.objects.count() + 1504 # Number to keep a continuity with the old site
Skia's avatar
Skia committed
79
            Customer(user=self.member, account_id=Customer.generate_account_id(last_id+1), amount=0).save()
Skia's avatar
Skia committed
80 81 82 83
            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
84
        self.member.make_home()
Sli's avatar
Sli committed
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
        if settings.IS_OLD_MYSQL_PRESENT:
            try: # Create subscription on the old site: TODO remove me!
                LOCATION = {
                        "SEVENANS": 5,
                        "BELFORT": 6,
                        "MONTBELIARD": 9,
                        "EBOUTIC": 5,
                        }
                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]))
                db.commit()
            except Exception as e:
                with open(settings.BASE_DIR+"/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)
                db.rollback()
127

128
    def get_absolute_url(self):
129
        return reverse('core:user_edit', kwargs={'user_id': self.member.pk})
130

131
    def __str__(self):
132 133 134 135 136
        if hasattr(self, "member") and self.member is not None:
            return self.member.username+' - '+str(self.pk)
        else:
            return 'No user - '+str(self.pk)

137

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

185

Skia's avatar
Skia committed
186
    def can_be_edited_by(self, user):
Skia's avatar
Skia committed
187
        return user.is_in_group(settings.SITH_MAIN_BOARD_GROUP) or user.is_root
Skia's avatar
Skia committed
188

189 190 191
    def is_valid_now(self):
        return self.subscription_start <= date.today() and date.today() <= self.subscription_end

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

if __name__ == "__main__":
    guy()