Merge branch 'feature-payment' into develop

This commit is contained in:
Jan Tuomi
2017-05-10 20:37:29 +03:00
8 changed files with 153 additions and 138 deletions
+2
View File
@@ -13,3 +13,5 @@ logs/
/media/ /media/
node_modules/ node_modules/
/.coverage /.coverage
db.sqlite3
requirements_henu.txt
+2 -2
View File
@@ -1,6 +1,6 @@
from django.contrib import admin from django.contrib import admin
from members.models import Member, MemberRequest from members.models import Member, Request
# Register your models here. # Register your models here.
admin.site.register(Member) admin.site.register(Member)
admin.site.register(MemberRequest) admin.site.register(Request)
@@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-03-29 16:28
from __future__ import unicode_literals
import datetime
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('members', '0002_auto_20170329_1857'),
]
operations = [
migrations.CreateModel(
name='Payment',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateTimeField(default=datetime.datetime(1970, 1, 1, 2, 0))),
('source', models.CharField(max_length=255)),
('first_name', models.CharField(max_length=255)),
('last_name', models.CharField(max_length=255)),
('email', models.EmailField(max_length=255)),
],
),
migrations.CreateModel(
name='Request',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('first_name', models.CharField(max_length=127)),
('last_name', models.CharField(max_length=127)),
('email', models.EmailField(max_length=254)),
('POR', models.CharField(default='ei_tiedossa', max_length=255)),
('AYY', models.BooleanField(default=False)),
('jas', models.BooleanField(default=False)),
('submitted', models.DateTimeField(default=django.utils.timezone.now)),
],
options={
'abstract': False,
},
),
migrations.RemoveField(
model_name='memberrequest',
name='member',
),
migrations.AlterField(
model_name='member',
name='POR',
field=models.CharField(default='ei_tiedossa', max_length=255),
),
migrations.AlterField(
model_name='member',
name='paid',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.DeleteModel(
name='MemberRequest',
),
migrations.AddField(
model_name='payment',
name='member',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='members.Member'),
),
]
+32 -93
View File
@@ -4,115 +4,54 @@ from datetime import datetime
from io import StringIO from io import StringIO
import csv import csv
class BaseMember(models.Model):
class Member(models.Model):
''' '''
Member model represets one member on the registry Base model for member.
''' '''
first_name = models.CharField(max_length=127) first_name = models.CharField(max_length=127)
last_name = models.CharField(max_length=127) last_name = models.CharField(max_length=127)
email = models.EmailField() email = models.EmailField()
POR = models.CharField(max_length=255) # place of residence POR = models.CharField(default="ei_tiedossa", max_length=255) # place of residence
AYY = models.BooleanField(default=False) AYY = models.BooleanField(default=False)
jas = models.BooleanField(default=False) jas = models.BooleanField(default=False)
created = models.DateTimeField(default=timezone.now)
paid = models.DateTimeField(default=datetime.fromtimestamp(0))
def get_dict(self): class Meta:
return { abstract = True
'id': self.id,
'first_name': self.first_name,
'last_name': self.last_name,
'email': self.email,
'POR': self.POR,
'AYY': self.AYY,
'jas': self.jas,
'created': date2str(self.created),
'paid': date2str(self.paid),
}
@classmethod
def create_from_dict(cls, d):
mbr = cls()
mbr.update_from_dict(d)
return mbr
def update_from_dict(self, d):
dmap = {
'first_name': reverse_map('first_name'),
'last_name': reverse_map('last_name'),
'email': reverse_map('email'),
'POR': reverse_map('POR'),
'AYY': reverse_map('AYY'),
'jas': reverse_map('jas'),
'paid': reverse_map('paid', str2date),
}
for k, v in d.items():
try:
self.__setattr__(dmap[k].key, dmap[k].parser(v))
except KeyError:
pass
self.save()
@classmethod
def import_csv(cls, csv_string):
reader = csv.reader(StringIO(csv_string.strip()))
response = {"status": "success", "errors": []}
try:
data = list(reader)
except ValueError:
return {"status": "failure", "errors": ["could not parse csv file"]}
affirmative_answers = ['yes', 'y', '1', 'true', "kyllä", "khyl"]
for row in data:
try:
obj = cls.objects.create(
first_name=row[0].strip(),
last_name=row[1].strip(),
email=row[2].strip(),
POR=row[3].strip(),
AYY=row[4].lower().strip() in affirmative_answers,
jas=row[5].lower().strip() in affirmative_answers,
paid=timezone.now()
)
print("added obj {}".format(obj))
except:
response["status"] = "failure"
response["errors"].append("failure adding item {}".format(", ".join(row)))
return response
def __str__(self):
return "{} {}".format(self.first_name, self.last_name)
class MemberRequest(models.Model): class Request(BaseMember):
member = models.ForeignKey(Member) '''
Member request model represents one member request.
'''
submitted = models.DateTimeField(default=timezone.now)
class Payment(models.Model):
'''
Payment model representing one payment event
'''
date = models.DateTimeField(default=datetime.fromtimestamp(0))
source = models.CharField(max_length=255)
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
email = models.EmailField(max_length=255)
member = models.ForeignKey('Member', on_delete=models.SET_NULL, blank=True, null=True)
def get_dict(self): def get_dict(self):
return { return {
'id': self.id, 'id': self.id,
'member': self.member.get_dict(), 'date': date2str(self.date),
'source': self.source,
'first_name': self.first_name,
'last_name': self.last_name,
'email': self.email,
'member': self.member.get_dict() if self.member else {}
} }
def date2str(date): class Member(BaseMember):
''' '''
Convert date to a standard date string Member model represets one member on the registry.
''' '''
if date is None: created = models.DateTimeField(default=timezone.now)
return None paid = models.DateTimeField(default=timezone.now) #this needs to be assigned as Payment.date
return date.strftime("%Y-%m-%d %H:%M:%S")
def str2date(s):
return datetime.strptime(s,"%Y-%m-%d %H:%M:%S")
class reverse_map:
def __init__(self, key, parser=lambda x: x):
self.key = key
self.parser = parser
+28 -6
View File
@@ -1,7 +1,7 @@
from rest_framework import serializers from rest_framework import serializers
from django.utils import timezone from django.utils import timezone
from datetime import datetime from datetime import datetime
from members.models import Member, MemberRequest from members.models import Member, Request
from django.conf import settings from django.conf import settings
@@ -37,10 +37,32 @@ class MemberSerializer(serializers.Serializer):
instance.save() instance.save()
return instance return instance
class MemberRequestSerializer(serializers.ModelSerializer): class MemberRequestSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True) id = serializers.IntegerField(read_only=True)
member = MemberSerializer() submitted = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
first_name = serializers.CharField(required=True, max_length=127)
last_name = serializers.CharField(required=True, max_length=127)
email = serializers.EmailField(min_length=None, max_length=None, required=True)
POR = serializers.CharField(max_length=255)
AYY = serializers.BooleanField(default=False)
jas = serializers.BooleanField(default=False)
class Meta: def created(self, validated_data):
model = MemberRequest '''
fields = ('id', 'member') Create and return a new MemberRequest instance, given the validated data.
'''
return MemberRequest.objects.create(**validated_data)
def update(self, instance, validated_data):
'''
Update and return an existing Member request instance given the validated data.
'''
instance.submitted = validated_data.get('submitted', instance.submitted)
instance.first_name = validated_data.get('first_name', instance.first_name)
instance.last_name = validated_data.get('last_name', instance.last_name)
instance.email = validated_data.get('email', instance.email)
instance.POR = validated_data.get('POR', instance.POR)
instance.AYY = validated_data.get('AYY', instance.AYY)
instance.jas = validated_data.get('jas', instance.jas)
instance.save()
return instance
-31
View File
@@ -1,31 +0,0 @@
{% extends "members_base.html" %}
{% block content %}
<div id="wrapper">
<!-- Sidebar -->
<div id="sidebar-wrapper">
<ul class="sidebar-nav">
<li><a href="#/list">Listaa jäsenet</a></li>
<li><a href="#/add">Lisää jäsen</a></li>
<li><a href="#/addmany">Lisää jäseniä</a></li>
<li><a href="#/applications">Jäsenhakemukset</a></li>
</ul>
</div>
<!-- /#sidebar-wrapper -->
<!-- Page Content -->
<div class="col-xs-12 col-sm-12 col-lg-12">
<div id="header" class="row">
<div class="col-xs-11 col-sm-11 col-lg-11">
<h1 style="text-align:center; margin-top:10px; margin-bottom: 10px;">Aalto-yliopiston Sähköinsinöörikilta RY:n jäsenrekisteri</h1>
</div>
<div class="col-xs-1 col-sm-1 col-lg-1">
<form action="/logout" method="post"> {% csrf_token %}
<input type="Submit" value="Logout" name="Logout" class="btn btn-danger" style="margin-top:12px;"/>
</form>
</div>
</div>
<div ng-view></div>
</div>
{% endblock content %}
+3 -4
View File
@@ -4,7 +4,7 @@ from django.views.decorators.http import require_http_methods
from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.csrf import ensure_csrf_cookie
from django.http import HttpResponse, HttpResponseBadRequest from django.http import HttpResponse, HttpResponseBadRequest
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from members.models import Member, MemberRequest from members.models import Member, Request
import json import json
from django.core.mail import send_mail from django.core.mail import send_mail
import requests import requests
@@ -32,7 +32,6 @@ class MembersList(generics.ListCreateAPIView):
permission_classes = (HasRights, permissions.IsAuthenticated, ) permission_classes = (HasRights, permissions.IsAuthenticated, )
throttle_classes = (BurstRateThrottle, SustainedRateThrottle, ) throttle_classes = (BurstRateThrottle, SustainedRateThrottle, )
class MemberDetails(generics.RetrieveUpdateDestroyAPIView): class MemberDetails(generics.RetrieveUpdateDestroyAPIView):
queryset = Member.objects.all() queryset = Member.objects.all()
serializer_class = MemberSerializer serializer_class = MemberSerializer
@@ -40,13 +39,13 @@ class MemberDetails(generics.RetrieveUpdateDestroyAPIView):
throttle_classes = (BurstRateThrottle, SustainedRateThrottle, ) throttle_classes = (BurstRateThrottle, SustainedRateThrottle, )
class MemberRequestList(generics.ListCreateAPIView): class MemberRequestList(generics.ListCreateAPIView):
queryset = MemberRequest.objects.all() queryset = Request.objects.all()
serializer_class = MemberRequestSerializer serializer_class = MemberRequestSerializer
permission_classes = (HasRights, permissions.IsAuthenticated, ) permission_classes = (HasRights, permissions.IsAuthenticated, )
throttle_classes = (BurstRateThrottle, SustainedRateThrottle, ) throttle_classes = (BurstRateThrottle, SustainedRateThrottle, )
class MemberRequestDetail(generics.RetrieveUpdateDestroyAPIView): class MemberRequestDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = MemberRequest.objects.all() queryset = Request.objects.all()
serializer_class = MemberRequestSerializer serializer_class = MemberRequestSerializer
permission_classes = (HasRights, permissions.IsAuthenticated, ) permission_classes = (HasRights, permissions.IsAuthenticated, )
throttle_classes = (BurstRateThrottle, SustainedRateThrottle, ) throttle_classes = (BurstRateThrottle, SustainedRateThrottle, )
+19 -2
View File
@@ -9,8 +9,7 @@ from django.conf import settings
django.setup() django.setup()
#django related stuff should be imported below this #django related stuff should be imported below this
from members.models import Member, MemberRequest from members.models import Member, Request
from infoscreen.models import Rotation, ExternalImageInfoItem, InfoInstance
from misc.namegenerator import generate_names from misc.namegenerator import generate_names
MEMBERAMOUNT = 30 MEMBERAMOUNT = 30
MEMBERREQUESTAMOUNT = 3 MEMBERREQUESTAMOUNT = 3
@@ -47,3 +46,21 @@ inst = InfoInstance.objects.create(
item=i_item, item=i_item,
duration=20.0 duration=20.0
) )
# for m in list(Member.objects.all())[:5]:
# MemberRequest.objects.create(member=m)
names = generate_names(MEMBERREQUESTAMOUNT)
maildomains = ["example.coms",'ggmail.om',"notmail.dom"] #intentionally wrong
places = ["Helsinki", "Espoo", "Korso","Kerava", "Kouvostoliitto"]
for i in range(MEMBERREQUESTAMOUNT):
f,l = names[i]
mail = "{}.{}@{}".format(f.lower(),l.lower(),random.choice(maildomains))
por = random.choice(places)
ayy = random.randint(0,1)
jas = random.randint(0,1)
Request.objects.create(first_name=f,
last_name=l,
email=mail,
POR=por,
AYY=ayy,
jas=jas)