From 74746fc0de48a96d09e5647f3dbbb9dfebf0e918 Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Fri, 12 May 2017 21:19:01 +0300 Subject: [PATCH] More members overhaul Relates to #44 --- members/forms.py | 9 +- members/models.py | 12 +- .../css/{jasenlista.css => members.css} | 35 ++- members/static/css/readme.md | 0 members/static/html/readme.md | 0 members/static/js/application_controllers.js | 63 ---- members/static/js/members_controllers.js | 279 ------------------ ...application.html => application_edit.html} | 0 ...n_base.html => application_form_base.html} | 11 - members/templates/application_index.html | 2 +- members/templates/application_list.html | 44 +++ members/templates/application_success.html | 2 +- members/templates/list_applications.html | 46 --- .../{add_member.html => member_add.html} | 0 ...many_members.html => member_add_many.html} | 0 ...onfirm.html => member_delete_confirm.html} | 0 .../{edit_member.html => member_edit.html} | 0 members/templates/member_list.html | 32 +- members/templates/members_base.html | 34 ++- members/templates/payment_add.html | 21 ++ members/templates/payment_list.html | 5 +- members/urls.py | 54 ++-- members/views.py | 93 ++++-- 23 files changed, 258 insertions(+), 484 deletions(-) rename members/static/css/{jasenlista.css => members.css} (72%) delete mode 100644 members/static/css/readme.md delete mode 100644 members/static/html/readme.md delete mode 100644 members/static/js/application_controllers.js delete mode 100644 members/static/js/members_controllers.js rename members/templates/{edit_application.html => application_edit.html} (100%) rename members/templates/{application_base.html => application_form_base.html} (59%) create mode 100644 members/templates/application_list.html delete mode 100644 members/templates/list_applications.html rename members/templates/{add_member.html => member_add.html} (100%) rename members/templates/{add_many_members.html => member_add_many.html} (100%) rename members/templates/{delete_member_confirm.html => member_delete_confirm.html} (100%) rename members/templates/{edit_member.html => member_edit.html} (100%) create mode 100644 members/templates/payment_add.html diff --git a/members/forms.py b/members/forms.py index d9b23c2..efe6825 100644 --- a/members/forms.py +++ b/members/forms.py @@ -1,6 +1,6 @@ from django import forms -from members.models import Member +from members.models import Member, Payment class MemberForm(forms.ModelForm): @@ -8,3 +8,10 @@ class MemberForm(forms.ModelForm): class Meta: model = Member fields = ['first_name', 'last_name', 'email', 'AYY', 'jas', 'POR'] + + +class PaymentForm(forms.ModelForm): + + class Meta: + model = Payment + fields = ['date', 'source', 'member'] diff --git a/members/models.py b/members/models.py index dc9ceae..d0e73cc 100644 --- a/members/models.py +++ b/members/models.py @@ -30,8 +30,12 @@ class Payment(models.Model): ''' Payment model representing one payment event ''' - date = models.DateTimeField(default=datetime.fromtimestamp(0)) - source = models.CharField(max_length=255) + date = models.DateTimeField(default=datetime.now()) + source = models.CharField(choices=[ + ('AYY', _('AYY')), + ('cash', _('Cash')), + ('bank_transfer', _('Bank transfer')), + ], max_length=255) member = models.ForeignKey('Member', on_delete=models.SET_NULL, blank=True, null=True) @@ -41,4 +45,6 @@ class Member(BaseMember): Member model represets one member on the registry. ''' created = models.DateTimeField(default=timezone.now) - paid = models.DateTimeField(default=timezone.now) #this needs to be assigned as Payment.date + + def __str__(self): + return "{} {}, {}".format(self.last_name, self.first_name, self.email) \ No newline at end of file diff --git a/members/static/css/jasenlista.css b/members/static/css/members.css similarity index 72% rename from members/static/css/jasenlista.css rename to members/static/css/members.css index ea0ee5b..048bbe5 100644 --- a/members/static/css/jasenlista.css +++ b/members/static/css/members.css @@ -1,3 +1,7 @@ +html, body { + font-size: 14px; +} + div { padding: 0.5rem; } @@ -6,6 +10,35 @@ input { padding: 0.5rem; } +/* fixes for the sidebar layout */ +#sidebar-wrapper { + background: #202020; + top: 0; + padding: 0; + +} + +.sidebar-nav { + width: initial; + left: 0; + width: 100%; + padding-top: 0.5rem; +} + +.sidebar-nav li ul { + padding-left: 0px; +} + +.sidebar-nav li span { + user-select: none; + cursor: default; +} + +#settings-button { + position: absolute; + bottom: 0; +} + #download-csv { margin-left: 20px; } @@ -81,4 +114,4 @@ input { .inline-title { display: inline; -} +} \ No newline at end of file diff --git a/members/static/css/readme.md b/members/static/css/readme.md deleted file mode 100644 index e69de29..0000000 diff --git a/members/static/html/readme.md b/members/static/html/readme.md deleted file mode 100644 index e69de29..0000000 diff --git a/members/static/js/application_controllers.js b/members/static/js/application_controllers.js deleted file mode 100644 index 1e3aa7b..0000000 --- a/members/static/js/application_controllers.js +++ /dev/null @@ -1,63 +0,0 @@ -//app - -app = angular.module('applicationApp', ['vcRecaptcha']); - -//tokens - -app.config(['$httpProvider', function ($httpProvider) { - $httpProvider.defaults.xsrfCookieName = 'csrftoken'; - $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken'; -}]); - -//helpers - -function notyfication(type,timeout){ - return function(msg){ - noty({ - 'text': msg, - 'layout': "bottomRight", - 'type': type, - 'timeout': timeout - }); - }; -} -var notyError = notyfication('error',2500); -var notySuccess = notyfication('success',2500); - -//controllers - -app.controller("applicationController", function($scope, $http, $location, $window, vcRecaptchaService) { - $scope.member = {}; - $scope.response = null; - $scope.widgetId = null; - $scope.model = { - key: "6LevHAcUAAAAAA45B7c-7qja-2aSwHztr9xb4K2Z" - }; - $scope.setResponse = function(response) { - $scope.response = response; - }; - $scope.setWidgetId = function(widgetId) { - $scope.widgetId = widgetId; - }; - $scope.cbExpiration = function() { - vcRecaptchaService.reload($scope.widgetId); - $scope.response = null; - }; - $scope.send = function() { - var valid; - //server side validation - $scope.member.reCaptchaResponse = vcRecaptchaService.getResponse() - console.log($scope.member.reCaptchaResponse); - if($scope.member.reCaptchaResponse === "") { - notyError("Ole hyvä ja täytä kuvavarmennus"); - } else { - $http.post("/members/api/request", $scope.member).then(function(data){ - notySuccess("Hakemus lähetetty!"); - $window.location.href = "/application/success"; - }, function(data){ - notyError("Jokin meni vikaan. Yritä uudelleen."); - vcRecaptchaService.reload($scope.widgetId); - }); - } - } -}); diff --git a/members/static/js/members_controllers.js b/members/static/js/members_controllers.js deleted file mode 100644 index 282fe9f..0000000 --- a/members/static/js/members_controllers.js +++ /dev/null @@ -1,279 +0,0 @@ -/* Controllers for member register views */ - -/* Generator function to create a "noty" notification function */ -function notyfication(type, timeout) { - return function(msg) { - noty({ - 'text': msg, - 'layout': "bottomRight", - 'type': type, - 'timeout': timeout - }); - }; -} - -/* Create functions to show error and success notifications in the bottom - * right corner of the viewport - * - * These functions take a single message string as a parameter */ -var notyError = notyfication('error', 2500); -var notySuccess = notyfication('success', 2500); - -function memberDataEditor(returnPath) { - return function($scope, $http, $window, $location) { - var id = memberId; - console.log("id: " + id); - $http.get("/members/api/member/" + id).then(function(response) { - $scope.member = response.data; - }); - - $scope.send = function() { - $http.put("/members/api/member/" + id, $scope.member).then(function(response){ - notySuccess("Jäsentiedot tallennettu"); - $window.location = returnPath; - }); - } - $scope.cancel = function() { //user canceled. return to list - $window.location = returnPath; - } - } -} -app.directive('ngConfirmClick', [ function() { return { - link: function (scope, element, attr) { - var clickAction = attr.confirmedClick; - element.bind('click', function (event) { - noty( { - text: 'Oletko aivan varma? T. Lasse Lehtinen', - layout: 'bottomRight', - buttons: [ { - addClass: 'btn btn-danger', text: 'Kyllä', onClick: function($noty) { - $noty.close(); - scope.$eval(clickAction); - } - }, - { - addClass: 'btn btn-primary', text: 'Ei', onClick: function($noty) { - $noty.close(); - } - } ] - } ); - }); - } -}}]); - -// controllers - -app.controller("getController", function($scope, $document, $http){ - /* List of all members that are fetched from the database */ - $scope.members = []; - - /* Fetch all members from the database and show all members in the table */ - $scope.updateMembers = function() { - $http.get("/members/api/members").then(function(response){ - $scope.members = response.data; - // map trues and falses to more user-friendly format - _.each($scope.members, function(m){ - m.jas = m.jas ? "Kyllä" : "Ei"; - m.AYY = m.AYY ? "Kyllä" : "Ei"; - }); - $scope.shown_members = $scope.members; - }); - }; - - /* Fetch a single member from the database by id and update its row */ - $scope.updateMember = function(id) { - $http.get("/members/api/member/" + id).then(function(response) { - for (var i = 0; i < $scope.shown_members.length; i++) { - var member = $scope.shown_members[i]; - if (String(member.id) == String(id)) { - member = response.data; - member.jas = member.jas ? "Kyllä" : "Ei"; - member.AYY = member.AYY ? "Kyllä" : "Ei"; - - $scope.shown_members[i] = member; - } - } - }); - }; - - /* Update the payment date of a single member to the current time and send - * the member to the database */ - $scope.updatePayment= function(id){ - $http.put("/members/api/member/"+id, { paid: moment().format("YYYY-MM-DD kk:mm:ss") }).then(function(response) { - $scope.updateMember(id); - notySuccess("Maksupäivämäärä päivitetty."); - }); - }; - - /* Redirect the browser to the CSV dump download endpoint */ - $scope.loadCSV = function() { - window.location = "/members/api/getCSV"; - }; - - /* Delete a single member by id */ - $scope.deleteMember = function(id) { - $http.delete("/members/api/member/" + id).then( - function(response) { - notySuccess("Poistaminen onnistui") - $scope.updateMembers(); - }, - function(response) { - notyError("Epäonnistui. Yritä uudelleen."); - $scope.updateMembers(); - } - ); - }; - - $scope.filterByDateComparison = function(members, datePicker, comparison) { - if (datePicker == null) { - return members; - } - - var result = []; - for (var i = 0; i < members.length; i++) { - if (comparison(members[i], datePicker)) { - result.push(members[i]); - } - } - return result; - }; - - /* Do a lazy search on the first name, last name and email fields - * If at least one of the aforementioned fields contains any of the search terms - * the search will be positive */ - $scope.filterBySearch = function(members) { - if ($scope.searchFilter == null) { - return members; - } - - var filterSearch = $scope.searchFilter.trim(); - if (filterSearch.length == 0) { - return members; - } - - var names = filterSearch.split(" "); - var result = []; - for (var i = 0; i < members.length; i++) { - var member = members[i]; - for (var j = 0; j < names.length; j++) { - var name = names[j].trim().toLowerCase(); - if (name.length == 0) continue; - - if (member.first_name.toLowerCase().includes(name) - || member.last_name.toLowerCase().includes(name) - || member.email.toLowerCase().includes(name)) { - - result.push(member); - break; - } - } - } - return result; - } - - /* Run all filters on the members list */ - $scope.doFilter = function() { - var result = $scope.members; - result = $scope.filterByDateComparison(result, $scope.addedBeforeDatePicker, function(member, date) { - return moment(member.created) < date }); - result = $scope.filterByDateComparison(result, $scope.addedAfterDatePicker, function(member, date) { - return moment(member.created) >= date }); - result = $scope.filterByDateComparison(result, $scope.paidBeforeDatePicker, function(member, date) { - return moment(member.paid) < date }); - result = $scope.filterByDateComparison(result, $scope.paidAfterDatePicker, function(member, date) { - return moment(member.paid) >= date }); - result = $scope.filterBySearch(result); - - $scope.shown_members = result; - } - - /* Clear all filter fields and reset the table view */ - $scope.clearFilter = function() { - $scope.paidBeforeDatePicker = null; - $scope.paidAfterDatePicker = null; - $scope.addedBeforeDatePicker = null; - $scope.addedAfterDatePicker = null; - $scope.searchFilter = null; - $scope.updateMembers(); - }; - - /* Run filters on enter keypress in search bar */ - $scope.pressKeyOnSearch = function(keyEvent) { - /* 13 is the id of the enter key */ - if (keyEvent.which === 13) { - $scope.doFilter(); - } - }; - - /* Start by resetting the whole thing */ - $scope.clearFilter(); -}); - -/* Controller for adding a member */ -app.controller("postController", function($scope, $http, $location, $window) { - $scope.member = {}; - $scope.send = function() { - $http.post("/members/api/member/", $scope.member).then(function(response){ - notySuccess("Jäsen lisätty!"); - $window.location = "/members/list"; - }); - - } -}); - -/* Controller for application page */ -app.controller("applController", function($scope, $http){ - $scope.applUpdateAll = function() { - $http.get("/members/api/requests").then(function(response){ - $scope.applications = response.data; - _.each($scope.applications, function(a){ - a.member.jas = a.member.jas ? "Kyllä" : "Ei"; - a.member.AYY = a.member.AYY ? "Kyllä" : "Ei"; - }); - }); - }; - - $scope.applUpdateAll(); - $scope.sendAppl = function(id) { - $http.post("/members/api/request/" + id).then( - function(response) { - notySuccess("Hakemus hyväksytty"); - $scope.applUpdateAll(); - }, - function(response) { - notyError("Hakemuksen hyväksyminen epäonnistui"); - $scope.applUpdateAll(); - } - ); - }; - $scope.deleteAppl = function(id) { - $http.delete("/members/api/request/" + id).then( - function(response) { - notySuccess("Hakemus hylätty!"); - $scope.applUpdateAll(); - }, - function(response) { - notyError("Hakemuksen hylkäys epäonnistui"); - $scope.applUpdateAll(); - } - ); - }; -}); - -app.controller("editController", memberDataEditor("/members/list")); -app.controller("applEditController", memberDataEditor("/members/applications")); - -app.controller("addManyController", function($scope, $http, $window) { - $scope.memberData = ''; - $scope.sendCSV = function() { - $http.post("/members/api/csvimport", {'csv': $scope.memberData}).then( - function(response) { - notySuccess("Lähetys onnistui"); - $window.location.reload(); - }, - function(response) { - notyError("Lähetys epäonnistui"); - } - ); - }; -}); diff --git a/members/templates/edit_application.html b/members/templates/application_edit.html similarity index 100% rename from members/templates/edit_application.html rename to members/templates/application_edit.html diff --git a/members/templates/application_base.html b/members/templates/application_form_base.html similarity index 59% rename from members/templates/application_base.html rename to members/templates/application_form_base.html index bed2a37..5f57e1b 100644 --- a/members/templates/application_base.html +++ b/members/templates/application_form_base.html @@ -14,24 +14,13 @@ - - - - - - - - - - - diff --git a/members/templates/application_index.html b/members/templates/application_index.html index 5cdf71c..9990d1c 100644 --- a/members/templates/application_index.html +++ b/members/templates/application_index.html @@ -1,4 +1,4 @@ -{% extends "application_base.html" %} +{% extends "application_form_base.html" %} {% load static %} {% block content %} diff --git a/members/templates/application_list.html b/members/templates/application_list.html new file mode 100644 index 0000000..e8442f8 --- /dev/null +++ b/members/templates/application_list.html @@ -0,0 +1,44 @@ +{% extends "members_base.html" %} + +{% load i18n %} + +{% block content %} +
+

{% trans "Member applications" %}

+ +
+ + + + + + + + + + + + + + + {% for application in application_list %} + + + + + + + + + + + + {% endfor %} + +
{% trans "Last name" %}{% trans "First name" %}{% trans "Email" %}{% trans "AYY member" %}{% trans "JAS recipient" %}{% trans "Residence" %}{% trans "Submitted" %}{% trans "Application count" %}: {{ application_count }}
{{ application.last_name }}{{ application.first_name }}{{ application.email }}{{ application.AYY }}{{ application.jas }}{{ application.POR }}{{ application.submitted }} + {% trans "Accept" %} + {% trans "Decline" %} +
+
+
+{% endblock content %} diff --git a/members/templates/application_success.html b/members/templates/application_success.html index 00aad06..15f3abf 100644 --- a/members/templates/application_success.html +++ b/members/templates/application_success.html @@ -1,4 +1,4 @@ -{% extends "application_base.html" %} +{% extends "application_form_base.html" %} {% block content %}

Hienoa! Jäsenhakemuksesi on nyt lähetetty.

diff --git a/members/templates/list_applications.html b/members/templates/list_applications.html deleted file mode 100644 index 078b98f..0000000 --- a/members/templates/list_applications.html +++ /dev/null @@ -1,46 +0,0 @@ -{% extends "members_base.html" %} - -{% load i18n %} - -{% block content %} -
-

{% trans "Member applications" %}

- -
- {% for application in applications %} -
-
{{ application.first_name }} {{ application.last_name }}
-
-
-
Sähköposti: {{ application.email }}
-
-
-
AYY-jäsen: {{ application.AYY }}
-
-
-
JAS-listaan: {{ application.jas }}
-
-
-
Asuinpaikka: {{ application.POR }}
-
-
-
Lisätty: {{ application.created }}
-
-
-
- - - -
-
-
-
- {% endfor %} -
- {% if application_count == 0 %} -
-

Ei jäsenhakemuksia :(

-
- {% endif %} -
-{% endblock content %} diff --git a/members/templates/add_member.html b/members/templates/member_add.html similarity index 100% rename from members/templates/add_member.html rename to members/templates/member_add.html diff --git a/members/templates/add_many_members.html b/members/templates/member_add_many.html similarity index 100% rename from members/templates/add_many_members.html rename to members/templates/member_add_many.html diff --git a/members/templates/delete_member_confirm.html b/members/templates/member_delete_confirm.html similarity index 100% rename from members/templates/delete_member_confirm.html rename to members/templates/member_delete_confirm.html diff --git a/members/templates/edit_member.html b/members/templates/member_edit.html similarity index 100% rename from members/templates/edit_member.html rename to members/templates/member_edit.html diff --git a/members/templates/member_list.html b/members/templates/member_list.html index 8fbc0a9..54a67c3 100644 --- a/members/templates/member_list.html +++ b/members/templates/member_list.html @@ -3,7 +3,6 @@ {% load static %} {% load i18n %} {% block content %} -
{% trans "Show filters" %} @@ -50,7 +49,7 @@
- +
@@ -65,22 +64,27 @@ - {% for member in member_list %} + {% for member_data in member_list %} - - - - - - - - + + + + + + + + diff --git a/members/templates/members_base.html b/members/templates/members_base.html index 4b58e98..9c6a850 100644 --- a/members/templates/members_base.html +++ b/members/templates/members_base.html @@ -4,7 +4,7 @@ {% load static %} {% load i18n %} - + @@ -24,12 +24,10 @@ - + @@ -38,11 +36,30 @@ @@ -65,5 +82,6 @@ {% endblock content %} {% include "footer.html" %} + diff --git a/members/templates/payment_add.html b/members/templates/payment_add.html new file mode 100644 index 0000000..d1f75b2 --- /dev/null +++ b/members/templates/payment_add.html @@ -0,0 +1,21 @@ +{% extends "members_base.html" %} + +{% load bootstrap3 %} +{% load i18n %} + +{% block content %} +
+

{% trans "Add payment" %}

+ +
+
{% csrf_token %} + {% bootstrap_form form %} + {% buttons %} + + {% endbuttons %} + +
+
+{% endblock content %} diff --git a/members/templates/payment_list.html b/members/templates/payment_list.html index 2527b18..1d4024e 100644 --- a/members/templates/payment_list.html +++ b/members/templates/payment_list.html @@ -3,7 +3,6 @@ {% load static %} {% load i18n %} {% block content %} -
{% trans "Show filters" %} @@ -50,7 +49,7 @@
-
{% trans "Last name" %}
{{ member.last_name }}{{ member.first_name }}{{ member.email }}{{ member.AYY }}{{ member.jas }}{{ member.POR }}{{ member.created }}{{ member.paid }}{{ member_data.member.last_name }}{{ member_data.member.first_name }}{{ member_data.member.email }}{{ member_data.member.AYY }}{{ member_data.member.jas }}{{ member_data.member.POR }}{{ member_data.member.created }} + {% if member_data.payment %} + {{ member_data.payment.date }} + {% else %} + {% trans "No payment" %} + {% endif %} + - - + - +
+
@@ -71,8 +70,6 @@ {% trans "No member data found" %} {% endif %} - -
{% trans "Date" %}{{ payment.last_name }}{{ payment.email }} diff --git a/members/urls.py b/members/urls.py index 096df1d..25cf9a7 100644 --- a/members/urls.py +++ b/members/urls.py @@ -2,21 +2,21 @@ from django.conf.urls import url from django.views.generic.base import RedirectView # members -from members.views import member_list -from members.views import add_member -from members.views import add_many_members -from members.views import edit_member -from members.views import submit_member -from members.views import update_member -from members.views import delete_member_confirm -from members.views import delete_member -from members.views import list_payments +from members.views import member_list, payment_add, payment_submit +from members.views import member_add +from members.views import member_add_many +from members.views import member_edit +from members.views import member_submit +from members.views import member_update +from members.views import member_delete_confirm +from members.views import member_delete +from members.views import payment_list #application -from members.views import application_index -from members.views import list_applications -from members.views import edit_application -from members.views import application_success_index +from members.views import application_form +from members.views import application_list +from members.views import application_edit +from members.views import application_form_success favicon_view = RedirectView.as_view(url='static/img/favicon.ico', permanent=True) @@ -27,36 +27,40 @@ urlpatterns = [ url(r'^list$', member_list), # add member form view - url(r'^add$', add_member), + url(r'^add$', member_add), # add many members view - url(r'^add_many$', add_many_members), + url(r'^add_many$', member_add_many), # edit member information view - url(r'^edit/(?P\d+)$', edit_member), + url(r'^edit/(?P\d+)$', member_edit), # delete confirmation view - url(r'^delete_member_confirm/(?P\d+)$', delete_member_confirm), + url(r'^delete_member_confirm/(?P\d+)$', member_delete_confirm), # list all member applications - url(r'^applications$', list_applications), + url(r'^applications$', application_list), # edit member application - url(r'^edit_application/(?P\d+)$', edit_application), + url(r'^edit_application/(?P\d+)$', application_edit), # post request targets - url(r'^submit_member$', submit_member), - url(r'^update_member$', update_member), - url(r'^delete_member$', delete_member), + url(r'^submit_member$', member_submit), + url(r'^update_member$', member_update), + url(r'^delete_member$', member_delete), + url(r'^submit_payment$', payment_submit), # the actual member application form - url(r'^application/$', application_index), + url(r'^application/$', application_form), # success page for the application - url(r'^application/success$', application_success_index), + url(r'^application/success$', application_form_success), # list all payment events - url(r'^payments', list_payments), + url(r'^payments', payment_list), + + # add payment event + url(r'^payment_add', payment_add), # favourite icon url(r'^favicon\.ico$', favicon_view), diff --git a/members/views.py b/members/views.py index 13ec942..c0bb194 100644 --- a/members/views.py +++ b/members/views.py @@ -5,23 +5,25 @@ from django.views.decorators.csrf import ensure_csrf_cookie from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseRedirect from django.core.mail import send_mail from django.conf import settings +from django.db.models import Max import json import requests import logging from members.models import Member, Request, Payment -from members.forms import MemberForm +from members.forms import MemberForm, PaymentForm # Logger function, you can use the same idea when implementing other loggers to other apps memberlogger = logging.getLogger(__name__) logging.basicConfig(format='[%(levelname)s]%(asctime)s %(message)s', level=settings.LOGGERLEVEL, filename=settings.LOGPATH) -''' -Recaptcha is used in member applications -''' def validate_recaptcha(response): + ''' + Recaptcha is used in member applications + ''' + values = { 'secret': settings.GOOGLE_RECAPTCHA_SECRET_KEY, 'response': response, @@ -51,45 +53,61 @@ def send_mail_wrapper(subject, message): @permission_required('members.change_member', login_url='/login') def member_list(request, *args, **kwargs): members = Member.objects.all() + + member_list = [] + for member in members: + obj = {'member': member, 'payment': None} + member_payments = Payment.objects.filter(member=member.id) + if len(member_payments) > 0: + last_payment = member_payments.aggregate(Max('date')) + print(last_payment) + + obj['payment'] = last_payment['date__max'] + + member_list.append(obj) + context = { - 'member_list': members, - 'member_count': len(members) + 'member_list': member_list, + 'member_count': len(member_list) } return render(request, 'member_list.html', context) @ensure_csrf_cookie @require_http_methods(["GET"]) @permission_required('members.change_member', login_url='/login') -def add_member(request, *args, **kwargs): +def member_add(request, *args, **kwargs): form = MemberForm() - return render(request, 'add_member.html', {'form': form}) + return render(request, 'member_add.html', {'form': form}) + @ensure_csrf_cookie @require_http_methods(["GET"]) @permission_required('members.change_member', login_url='/login') -def delete_member_confirm(request, *args, **kwargs): +def member_delete_confirm(request, *args, **kwargs): i = kwargs.pop('index', None) if i is None: return HttpResponse(status=500, error="{'error': 'No member id specified'}") else: member = Member.objects.get(id=i) form = MemberForm(instance=member) - return render(request, 'delete_member_confirm.html', {'member_id': i, 'form': form}) + return render(request, 'member_delete_confirm.html', {'member_id': i, 'form': form}) + @ensure_csrf_cookie @require_http_methods(["GET"]) @permission_required('members.change_member', login_url='/login') -def add_many_members(request, *args, **kwargs): - return render(request, 'add_many_members.html', {}) +def member_add_many(request, *args, **kwargs): + return render(request, 'member_add_many.html', {}) + @ensure_csrf_cookie @require_http_methods(["POST"]) @permission_required('members.change_member', login_url='/login') -def submit_member(request, *args, **kwargs): +def member_submit(request, *args, **kwargs): form = MemberForm(request.POST) if form.is_valid(): form.save() - logging.info("Saved new member to member register with the following info: {}".format(form)) + memberlogger.info("Saved new member to member register with the following info: {}".format(form)) return HttpResponseRedirect('/members') else: print(form.errors) @@ -99,7 +117,7 @@ def submit_member(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["POST"]) @permission_required('members.change_member', login_url='/login') -def update_member(request, *args, **kwargs): +def member_update(request, *args, **kwargs): form = MemberForm(request.POST) if form.is_valid(): id = request.POST['id'] @@ -107,7 +125,7 @@ def update_member(request, *args, **kwargs): form = MemberForm(request.POST, instance=member) form.save() - logging.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') else: print(form.errors) @@ -117,7 +135,7 @@ def update_member(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["POST"]) @permission_required('members.change_member', login_url='/login') -def delete_member(request, *args, **kwargs): +def member_delete(request, *args, **kwargs): try: id = request.POST['id'] except KeyError: @@ -136,54 +154,54 @@ def delete_member(request, *args, **kwargs): @ensure_csrf_cookie @require_http_methods(["GET"]) @permission_required('members.change_member', login_url='/login') -def list_applications(request, *args, **kwargs): +def application_list(request, *args, **kwargs): applications = Request.objects.all() application_count = len(applications) context = { - 'applications': applications, + 'application_list': applications, 'application_count': application_count } - return render(request, 'list_applications.html', context) + return render(request, 'application_list.html', context) @ensure_csrf_cookie @require_http_methods(["GET"]) @permission_required('members.change_member', login_url='/login') -def edit_member(request, *args, **kwargs): +def member_edit(request, *args, **kwargs): i = kwargs.pop('index', None) if i is None: return HttpResponse(status=500, error="{'error': 'No member id specified'}") else: member = Member.objects.get(id=i) form = MemberForm(instance=member) - return render(request, 'edit_member.html', {'member_id': i, 'form': form}) + return render(request, 'member_edit.html', {'member_id': i, 'form': form}) @ensure_csrf_cookie @require_http_methods(["GET"]) @permission_required('members.change_member', login_url='/login') -def edit_application(request, *args, **kwargs): +def application_edit(request, *args, **kwargs): i = kwargs.pop('index', None) if i is None: return HttpResponse(status=500, error="{'error': 'No member id specified'}") else: - return render(request, 'edit_application.html', {'member_id' : i}) + return render(request, 'application_edit.html', {'member_id' : i}) @ensure_csrf_cookie -def application_index(request, *args, **kwargs): +def application_form(request, *args, **kwargs): return render(request, 'application_index.html', {}) @ensure_csrf_cookie -def application_success_index(request, *args, **kwargs): +def application_form_success(request, *args, **kwargs): return render(request, 'application_success.html', {}) @ensure_csrf_cookie @require_http_methods(["GET"]) @permission_required('members.change_member', login_url='/login') -def list_payments(request, *args, **kwargs): +def payment_list(request, *args, **kwargs): payments = Payment.objects.all() context = { 'payment_list': payments, @@ -192,6 +210,27 @@ def list_payments(request, *args, **kwargs): return render(request, 'payment_list.html', context) +@ensure_csrf_cookie +@require_http_methods(["GET"]) +@permission_required('members.change_member', login_url='/login') +def payment_add(request, *args, **kwargs): + form = PaymentForm() + return render(request, 'payment_add.html', {'form': form}) + + +@ensure_csrf_cookie +@require_http_methods(["POST"]) +@permission_required('members.change_member', login_url='/login') +def payment_submit(request, *args, **kwargs): + form = PaymentForm(request.POST) + if form.is_valid(): + form.save() + memberlogger.info("Saved new payment to member register with the following info: {}".format(form)) + return HttpResponseRedirect('/members/payments') + else: + print(form.errors) + return HttpResponse('oh shit') + @ensure_csrf_cookie @require_http_methods(["POST"]) @permission_required('members.change_member', login_url='/login')