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/
node_modules/
/.coverage
db.sqlite3
requirements_henu.txt
+2 -2
View File
@@ -1,6 +1,6 @@
from django.contrib import admin
from members.models import Member, MemberRequest
from members.models import Member, Request
# Register your models here.
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
import csv
class Member(models.Model):
class BaseMember(models.Model):
'''
Member model represets one member on the registry
Base model for member.
'''
first_name = models.CharField(max_length=127)
last_name = models.CharField(max_length=127)
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)
jas = models.BooleanField(default=False)
created = models.DateTimeField(default=timezone.now)
paid = models.DateTimeField(default=datetime.fromtimestamp(0))
class Meta:
abstract = True
class Request(BaseMember):
'''
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):
return {
'id': self.id,
'date': date2str(self.date),
'source': self.source,
'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):
member = models.ForeignKey(Member)
def get_dict(self):
return {
'id': self.id,
'member': self.member.get_dict(),
'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:
return None
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
created = models.DateTimeField(default=timezone.now)
paid = models.DateTimeField(default=timezone.now) #this needs to be assigned as Payment.date
+28 -6
View File
@@ -1,7 +1,7 @@
from rest_framework import serializers
from django.utils import timezone
from datetime import datetime
from members.models import Member, MemberRequest
from members.models import Member, Request
from django.conf import settings
@@ -37,10 +37,32 @@ class MemberSerializer(serializers.Serializer):
instance.save()
return instance
class MemberRequestSerializer(serializers.ModelSerializer):
class MemberRequestSerializer(serializers.Serializer):
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:
model = MemberRequest
fields = ('id', 'member')
def created(self, validated_data):
'''
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.http import HttpResponse, HttpResponseBadRequest
from django.core.exceptions import ValidationError
from members.models import Member, MemberRequest
from members.models import Member, Request
import json
from django.core.mail import send_mail
import requests
@@ -32,7 +32,6 @@ class MembersList(generics.ListCreateAPIView):
permission_classes = (HasRights, permissions.IsAuthenticated, )
throttle_classes = (BurstRateThrottle, SustainedRateThrottle, )
class MemberDetails(generics.RetrieveUpdateDestroyAPIView):
queryset = Member.objects.all()
serializer_class = MemberSerializer
@@ -40,13 +39,13 @@ class MemberDetails(generics.RetrieveUpdateDestroyAPIView):
throttle_classes = (BurstRateThrottle, SustainedRateThrottle, )
class MemberRequestList(generics.ListCreateAPIView):
queryset = MemberRequest.objects.all()
queryset = Request.objects.all()
serializer_class = MemberRequestSerializer
permission_classes = (HasRights, permissions.IsAuthenticated, )
throttle_classes = (BurstRateThrottle, SustainedRateThrottle, )
class MemberRequestDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = MemberRequest.objects.all()
queryset = Request.objects.all()
serializer_class = MemberRequestSerializer
permission_classes = (HasRights, permissions.IsAuthenticated, )
throttle_classes = (BurstRateThrottle, SustainedRateThrottle, )
+19 -2
View File
@@ -9,8 +9,7 @@ from django.conf import settings
django.setup()
#django related stuff should be imported below this
from members.models import Member, MemberRequest
from infoscreen.models import Rotation, ExternalImageInfoItem, InfoInstance
from members.models import Member, Request
from misc.namegenerator import generate_names
MEMBERAMOUNT = 30
MEMBERREQUESTAMOUNT = 3
@@ -47,3 +46,21 @@ inst = InfoInstance.objects.create(
item=i_item,
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)