Add payment edit and delete

Application editing still WIP
This commit is contained in:
Jan Tuomi
2017-05-17 13:28:06 +03:00
parent 2b5101566c
commit cae57d973e
11 changed files with 227 additions and 36 deletions
@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2017-05-17 10:09
from __future__ import unicode_literals
import datetime
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('members', '0005_auto_20170513_1029'),
]
operations = [
migrations.AlterField(
model_name='payment',
name='date',
field=models.DateTimeField(default=datetime.datetime(2017, 5, 17, 13, 9, 21, 49238)),
),
]
+7 -4
View File
@@ -18,6 +18,9 @@ class BaseMember(models.Model):
class Meta: class Meta:
abstract = True abstract = True
def __str__(self):
return "{} {}, {}".format(self.last_name, self.first_name, self.email)
class Request(BaseMember): class Request(BaseMember):
''' '''
@@ -39,12 +42,12 @@ class Payment(models.Model):
member = models.ForeignKey('Member', on_delete=models.SET_NULL, blank=True, null=True) member = models.ForeignKey('Member', on_delete=models.SET_NULL, blank=True, null=True)
def __str__(self):
return 'Payment no. {}, {}'.format(self.id, str(self.date))
class Member(BaseMember): class Member(BaseMember):
''' '''
Member model represets one member on the registry. Member model represets one member on the registry.
''' '''
created = models.DateTimeField(default=timezone.now) created = models.DateTimeField(default=timezone.now)
def __str__(self):
return "{} {}, {}".format(self.last_name, self.first_name, self.email)
+14 -2
View File
@@ -45,7 +45,7 @@ input {
cursor: default; cursor: default;
} }
@media (max-width: 768px) { @media (max-width: 767px) {
table { table {
table-layout: fixed; table-layout: fixed;
@@ -102,7 +102,7 @@ input {
} }
} }
@media (min-width: 768px) { @media (min-width: 769px) {
.logout-container { .logout-container {
bottom: 1rem; bottom: 1rem;
position: absolute; position: absolute;
@@ -195,3 +195,15 @@ input {
.inline-title { .inline-title {
display: inline; display: inline;
} }
.ellipsis-menu {
height: 2rem;
}
.data-table-button {
width: 100%;
}
.readonly {
pointer-events: none;
}
+19
View File
@@ -1,21 +1,40 @@
import django_tables2 as tables import django_tables2 as tables
from django.utils.translation import ugettext as _
from members.models import Member, Payment, Request from members.models import Member, Payment, Request
class MemberTable(tables.Table): class MemberTable(tables.Table):
options = tables.TemplateColumn(
'<a class="data-table-button btn btn-primary" href="/members/edit/{{ record.id }}">' +
_('Edit') +
'</a>'
)
class Meta: class Meta:
model = Member model = Member
class PaymentTable(tables.Table): class PaymentTable(tables.Table):
options = tables.TemplateColumn(
'<a class="data-table-button btn btn-primary" href="/members/edit_payment/{{ record.id }}">' +
_('Edit') +
'</a>'
)
class Meta: class Meta:
model = Payment model = Payment
class RequestTable(tables.Table): class RequestTable(tables.Table):
options = tables.TemplateColumn(
'<a class="data-table-button btn btn-primary" href="/members/edit_application/{{ record.id }}">' +
_('Edit') +
'</a>'
)
class Meta: class Meta:
model = Request model = Request
+6 -4
View File
@@ -5,11 +5,13 @@
{% block content %} {% block content %}
<div> <div>
<h3>{% trans "Are you sure you want to delete this member?" %}</h3> <div>
<h3>{% trans "Are you sure you want to delete this member?" %}</h3>
</div>
<div id="input_form"> <div>
<table class="table" > <table class="table readonly" >
{{ form.as_table }} {{ form }}
</table> </table>
<form name="memberForm" action="/members/delete_member" method="post" class="form">{% csrf_token %} <form name="memberForm" action="/members/delete_member" method="post" class="form">{% csrf_token %}
<input type="hidden" name="id" value="{{ member_id }}"> <input type="hidden" name="id" value="{{ member_id }}">
+4 -1
View File
@@ -5,7 +5,9 @@
{% block content %} {% block content %}
<div> <div>
<h3>{% trans "Add member" %}</h3> <div>
<h3>{% trans "Edit member" %}</h3>
</div>
<div id="input_form"> <div id="input_form">
<form name="memberForm" action="/members/update_member" method="post" class="form">{% csrf_token %} <form name="memberForm" action="/members/update_member" method="post" class="form">{% csrf_token %}
@@ -15,6 +17,7 @@
<button type="submit" class="btn btn-primary"> <button type="submit" class="btn btn-primary">
{% trans "Save" %} {% trans "Save" %}
</button> </button>
<a href="/members/delete_member_confirm/{{ member_id }}" class="btn btn-danger">{% trans "Delete" %}</a>
{% endbuttons %} {% endbuttons %}
</form> </form>
</div> </div>
+1 -1
View File
@@ -56,7 +56,7 @@
<span class="text-primary">{% trans "Payments" %}</span> <span class="text-primary">{% trans "Payments" %}</span>
<ul> <ul>
<li><a href="/members/payments">{% trans "List payments" %}</a></li> <li><a href="/members/payments">{% trans "List payments" %}</a></li>
<li><a href="/members/payment_add">{% trans "Add payment" %}</a></li> <li><a href="/members/add_payment">{% trans "Add payment" %}</a></li>
</ul> </ul>
</li> </li>
<li> <li>
@@ -0,0 +1,24 @@
{% extends "members_base.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% block content %}
<div>
<div>
<h3>{% trans "Are you sure you want to delete this payment?" %}</h3>
</div>
<div>
<table class="table readonly" >
{{ form }}
</table>
<form name="paymentForm" action="/members/delete_payment" method="post" class="form">{% csrf_token %}
<input type="hidden" name="id" value="{{ payment_id }}">
<button type="submit" class="btn btn-danger">
{% trans "Yes, I'm sure" %}
</button>
</form>
</div>
</div>
{% endblock content %}
+25
View File
@@ -0,0 +1,25 @@
{% extends "members_base.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% block content %}
<div>
<div>
<h3>{% trans "Edit payment" %}</h3>
</div>
<div>
<form name="paymentForm" action="/members/update_payment" method="post" class="form">{% csrf_token %}
<input type="hidden" name="id" value="{{ payment_id }}">
{% bootstrap_form form %}
{% buttons %}
<button type="submit" class="btn btn-primary">
{% trans "Save" %}
</button>
<a href="/members/delete_payment_confirm/{{ payment_id }}" class="btn btn-danger">{% trans "Delete" %}</a>
{% endbuttons %}
</form>
</div>
</div>
{% endblock content %}
+16 -5
View File
@@ -2,7 +2,10 @@ from django.conf.urls import url
from django.views.generic.base import RedirectView from django.views.generic.base import RedirectView
# members # members
from members.views import member_list, payment_add, payment_submit, settings_page from members.views import member_list, payment_add, payment_submit
from members.views import settings_page, payment_edit
from members.views import payment_delete_confirm
from members.views import payment_delete, payment_update
from members.views import member_add from members.views import member_add
from members.views import member_add_many from members.views import member_add_many
from members.views import member_edit from members.views import member_edit
@@ -12,7 +15,7 @@ from members.views import member_delete_confirm
from members.views import member_delete from members.views import member_delete
from members.views import payment_list from members.views import payment_list
#application # application
from members.views import application_form from members.views import application_form
from members.views import application_list from members.views import application_list
from members.views import application_edit from members.views import application_edit
@@ -49,6 +52,8 @@ urlpatterns = [
url(r'^update_member$', member_update), url(r'^update_member$', member_update),
url(r'^delete_member$', member_delete), url(r'^delete_member$', member_delete),
url(r'^submit_payment$', payment_submit), url(r'^submit_payment$', payment_submit),
url(r'^update_payment$', payment_update),
url(r'^delete_payment$', payment_delete),
# the actual member application form # the actual member application form
url(r'^application/$', application_form), url(r'^application/$', application_form),
@@ -57,13 +62,19 @@ urlpatterns = [
url(r'^application/success$', application_form_success), url(r'^application/success$', application_form_success),
# list all payment events # list all payment events
url(r'^payments', payment_list), url(r'^payments$', payment_list),
# add payment event # add payment event
url(r'^payment_add', payment_add), url(r'^add_payment$', payment_add),
# edit payment event
url(r'^edit_payment/(?P<index>\d+)$', payment_edit),
# delete confirmation view
url(r'^delete_payment_confirm/(?P<index>\d+)$', payment_delete_confirm),
# settings page # settings page
url(r'^settings', settings_page), url(r'^settings$', settings_page),
# favourite icon # favourite icon
url(r'^favicon\.ico$', favicon_view), url(r'^favicon\.ico$', favicon_view),
+90 -19
View File
@@ -2,7 +2,7 @@ from django.shortcuts import render
from django.contrib.auth.decorators import permission_required from django.contrib.auth.decorators import permission_required
from django.views.decorators.http import require_http_methods 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, HttpResponseRedirect from django.http import HttpResponse, HttpResponseRedirect
from django.core.mail import send_mail from django.core.mail import send_mail
from django.conf import settings from django.conf import settings
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
@@ -25,6 +25,9 @@ logging.basicConfig(format='[%(levelname)s]%(asctime)s %(message)s', level=setti
def validate_recaptcha(response): def validate_recaptcha(response):
''' '''
Recaptcha is used in member applications Recaptcha is used in member applications
:param response:
:return: Boolean, success or not
''' '''
values = { values = {
@@ -34,11 +37,12 @@ def validate_recaptcha(response):
url = "https://www.google.com/recaptcha/api/siteverify" url = "https://www.google.com/recaptcha/api/siteverify"
headers = {'Content-type': 'application/x-www-form-urlencoded'} headers = {'Content-type': 'application/x-www-form-urlencoded'}
resp = requests.post(url, values, headers=headers) resp = requests.post(url, values, headers=headers)
result = json.loads(resp.text) try:
memberlogger.info(result) result = json.loads(resp.text)
if not result["success"]: memberlogger.info('Recaptcha response: {}'.format(result))
return result["success"]
except:
return False return False
return True
def send_mail_wrapper(subject, message): def send_mail_wrapper(subject, message):
@@ -71,6 +75,7 @@ def convert_table_to_html(table, request):
fixed = table_as_html.replace(r'href="?', r'href="{}?'.format(path)) fixed = table_as_html.replace(r'href="?', r'href="{}?'.format(path))
return fixed return fixed
@ensure_csrf_cookie @ensure_csrf_cookie
@require_http_methods(["GET"]) @require_http_methods(["GET"])
@permission_required('members.change_member', login_url='/login') @permission_required('members.change_member', login_url='/login')
@@ -107,7 +112,7 @@ def member_add(request, *args, **kwargs):
def member_delete_confirm(request, *args, **kwargs): def member_delete_confirm(request, *args, **kwargs):
i = kwargs.pop('index', None) i = kwargs.pop('index', None)
if i is None: if i is None:
return HttpResponse(status=500, error="{'error': 'No member id specified'}") return render(request, 'error.html', {'error': _('No member id specified')})
else: else:
member = Member.objects.get(id=i) member = Member.objects.get(id=i)
form = MemberForm(instance=member) form = MemberForm(instance=member)
@@ -150,10 +155,11 @@ def member_update(request, *args, **kwargs):
form.save() form.save()
memberlogger.info("Updated member in member register with the following info: {}".format(form)) memberlogger.info("Updated member in member register with the following info: {}".format(form))
return HttpResponseRedirect('/members') notification = "{} {} {}.".format(_("Successfully updated member"),
member.last_name, member.first_name)
return HttpResponseRedirect('/members/list?notification={}'.format(html.escape(notification)))
else: else:
print(form.errors) return render(request, 'error.html', {'error': _('Could not update member object')})
return HttpResponse('oh shit')
@ensure_csrf_cookie @ensure_csrf_cookie
@@ -167,12 +173,13 @@ def member_delete(request, *args, **kwargs):
try: try:
member = Member.objects.get(id=id) member = Member.objects.get(id=id)
notification = "{} {} {}.".format(_("Successfully deleted member"),
member.last_name, member.first_name)
member.delete() member.delete()
return HttpResponseRedirect('/members') memberlogger.info("Delete member in member register with the following id: {}".format(id))
return HttpResponseRedirect('/members/list?notification={}'.format(html.escape(notification)))
except: except:
resp = HttpResponse('{"error" : "could not delete object"}') return render(request, 'error.html', {'error': _('Could not delete member object')})
resp.status_code = 500
return resp
@ensure_csrf_cookie @ensure_csrf_cookie
@@ -181,7 +188,7 @@ def member_delete(request, *args, **kwargs):
def member_edit(request, *args, **kwargs): def member_edit(request, *args, **kwargs):
i = kwargs.pop('index', None) i = kwargs.pop('index', None)
if i is None: if i is None:
return HttpResponse(status=500, error="{'error': 'No member id specified'}") return render(request, 'error.html', {'error': _('No member id specified')})
else: else:
member = Member.objects.get(id=i) member = Member.objects.get(id=i)
form = MemberForm(instance=member) form = MemberForm(instance=member)
@@ -197,8 +204,7 @@ def application_list(request, *args, **kwargs):
table = RequestTable(applications, table = RequestTable(applications,
request=request, request=request,
exclude=['id'], exclude=['id'],
attrs={'class': 'table table-bordered table-hover'}, attrs={'class': 'table table-bordered table-hover'})
)
table.paginate(page=request.GET.get('page', 1), per_page=25) table.paginate(page=request.GET.get('page', 1), per_page=25)
table_html = convert_table_to_html(table, request) table_html = convert_table_to_html(table, request)
@@ -216,9 +222,9 @@ def application_list(request, *args, **kwargs):
def application_edit(request, *args, **kwargs): def application_edit(request, *args, **kwargs):
i = kwargs.pop('index', None) i = kwargs.pop('index', None)
if i is None: if i is None:
return HttpResponse(status=500, error="{'error': 'No member id specified'}") return render(request, 'error.html', {'error': _('No application id specified')})
else: else:
return render(request, 'application_edit.html', {'member_id' : i}) return render(request, 'application_edit.html', {'member_id': i})
@ensure_csrf_cookie @ensure_csrf_cookie
@@ -270,17 +276,82 @@ def payment_submit(request, *args, **kwargs):
form.save() form.save()
memberlogger.info("Saved new payment to member register with the following info: {}".format(form)) memberlogger.info("Saved new payment to member register with the following info: {}".format(form))
notification = "{} {}.".format(_("Successfully added payment for member"), notification = "{} {}.".format(_("Successfully added payment for member"),
form.cleaned_data['member']) form.cleaned_data['member'])
return HttpResponseRedirect('/members/payments?notification={}'.format(html.escape(notification))) return HttpResponseRedirect('/members/payments?notification={}'.format(html.escape(notification)))
else: else:
return render(request, 'error.html', {'error': form.errors}) return render(request, 'error.html', {'error': form.errors})
@ensure_csrf_cookie
@require_http_methods(["GET"])
@permission_required('members.change_member', login_url='/login')
def payment_edit(request, *args, **kwargs):
i = kwargs.pop('index', None)
if i is None:
return render(request, 'error.html', {'error': _('No payment id specified')})
else:
payment = Payment.objects.get(id=i)
form = PaymentForm(instance=payment)
return render(request, 'payment_edit.html', {'payment_id': i, 'form': form})
@ensure_csrf_cookie
@require_http_methods(["GET"])
@permission_required('members.change_member', login_url='/login')
def payment_delete_confirm(request, *args, **kwargs):
i = kwargs.pop('index', None)
if i is None:
return render(request, 'error.html', {'error': _('No payment id specified')})
else:
payment = Payment.objects.get(id=i)
form = PaymentForm(instance=payment)
return render(request, 'payment_delete_confirm.html', {'payment_id': i, 'form': form})
@ensure_csrf_cookie
@require_http_methods(["POST"])
@permission_required('members.change_member', login_url='/login')
def payment_delete(request, *args, **kwargs):
try:
id = request.POST['id']
except KeyError:
return HttpResponse(401)
try:
payment = Payment.objects.get(id=id)
notification = "{} {}.".format(_("Successfully deleted payment"), str(payment))
payment.delete()
memberlogger.info("Delete payment '{}' in member register".format(str(payment)))
return HttpResponseRedirect('/members/payments?notification={}'.format(html.escape(notification)))
except:
return render(request, 'error.html', {'error': _('Could not delete payment object')})
@ensure_csrf_cookie
@require_http_methods(["POST"])
@permission_required('members.change_member', login_url='/login')
def payment_update(request, *args, **kwargs):
form = PaymentForm(request.POST)
if form.is_valid():
id = request.POST['id']
payment = Payment.objects.get(id=id)
form = PaymentForm(request.POST, instance=payment)
form.save()
memberlogger.info("Updated member in member register with the following info: {}".format(form))
notification = "{} {}.".format(_("Successfully updated payment"), str(payment))
return HttpResponseRedirect('/members/payments?notification={}'.format(html.escape(notification)))
else:
return render(request, 'error.html', {'error': _('Could not update payment object')})
@ensure_csrf_cookie @ensure_csrf_cookie
@require_http_methods(["GET"]) @require_http_methods(["GET"])
@permission_required('members.change_member', login_url='/login') @permission_required('members.change_member', login_url='/login')
def settings_page(request, *args, **kwargs): def settings_page(request, *args, **kwargs):
return render(request, 'settings.html', {}) return render(request, 'settings.html', {})
@ensure_csrf_cookie @ensure_csrf_cookie
@require_http_methods(["POST"]) @require_http_methods(["POST"])
@permission_required('members.change_member', login_url='/login') @permission_required('members.change_member', login_url='/login')