Improve subscription and add it to admin app

This commit is contained in:
Skia
2016-01-28 17:42:22 +01:00
parent f71ce2f7df
commit 8fc360a977
14 changed files with 50 additions and 37 deletions

0
subscription/__init__.py Normal file
View File

8
subscription/admin.py Normal file
View File

@ -0,0 +1,8 @@
from django.contrib import admin
from subscription.models import Member, Subscription
admin.site.register(Member)
admin.site.register(Subscription)

View File

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
from django.conf import settings
class Migration(migrations.Migration):
dependencies = [
('core', '0005_auto_20160128_0842'),
]
operations = [
migrations.CreateModel(
name='Member',
fields=[
('user', models.OneToOneField(to=settings.AUTH_USER_MODEL, primary_key=True, serialize=False)),
],
),
migrations.CreateModel(
name='Subscription',
fields=[
('id', models.AutoField(auto_created=True, serialize=False, verbose_name='ID', primary_key=True)),
('subscription_type', models.CharField(choices=[('cursus-branche', 'Cursus Branche'), ('cursus-tronc-commun', 'Cursus Tronc Commun'), ('deux-semestres', 'Deux semestres'), ('un-semestre', 'Un semestre')], verbose_name='subscription type', max_length=255)),
('subscription_start', models.DateField(verbose_name='subscription start')),
('subscription_end', models.DateField(verbose_name='subscription end')),
('payment_method', models.CharField(choices=[('cheque', 'Chèque'), ('cash', 'Espèce'), ('other', 'Autre')], verbose_name='payment method', max_length=255)),
('member', models.ForeignKey(to='subscription.Member', related_name='subscriptions')),
],
options={
'ordering': ['subscription_start'],
},
),
]

View File

128
subscription/models.py Normal file
View File

@ -0,0 +1,128 @@
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()
def __str__(self):
return self.user.username
class Subscription(models.Model):
member = models.ForeignKey(Member, related_name='subscriptions')
subscription_type = models.CharField(_('subscription type'),
max_length=255,
choices=((k, v['name']) for k,v in sorted(settings.AE_SUBSCRIPTIONS.items())))
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)
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)
class Meta:
ordering = ['subscription_start',]
def __str__(self):
return self.member.user.username+' - '+str(self.pk)
@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()

View File

@ -0,0 +1,18 @@
{% extends "core/base.html" %}
{% block title %}
{% if profile %}
Edit {{ member.user.get_display_name }}'s subscription
{% endif %}
{% endblock %}
{% block content %}
<h3>Edit subscription</h3>
{# <p><a href="{% url 'core:user_profile' object.member.user.id %}">Go to profile</a></p> #}
{# <p>You're editing the subscription of <strong>{{ member.user.get_display_name }}</strong></p>#}
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<p><input type="submit" value="Save!" /></p>
</form>
{% endblock %}

3
subscription/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

11
subscription/urls.py Normal file
View File

@ -0,0 +1,11 @@
from django.conf.urls import url, include
from subscription.views import *
urlpatterns = [
# Subscription views
url(r'^subscription/(?P<user_id>[0-9]+)/$', NewSubscription.as_view(), name='subscription'),
]

21
subscription/views.py Normal file
View File

@ -0,0 +1,21 @@
from django.shortcuts import render
from django.views.generic.edit import UpdateView, CreateView
from django import forms
from django.forms import Select
from django.conf import settings
from subscription.models import Member, Subscription
from core.views import CanEditMixin, CanEditPropMixin, CanViewMixin
class SubscriptionForm(forms.ModelForm):
class Meta:
model = Subscription
fields = ['subscription_type', 'payment_method']
#widgets = {
# 'subscription_type': Select(choices={(k.lower(), k+" - "+str(v['price'])+"€"+str(Subscription.compute_end(2))) for k,v in settings.AE_SUBSCRIPTIONS.items()}),
#}
class NewSubscription(CanEditMixin, CreateView):
template_name = 'subscription/subscription.html'
form_class = SubscriptionForm