Merge branch 'develop' into feature-pep8-fixes

This commit is contained in:
Jan Tuomi
2017-09-20 23:32:41 +03:00
16 changed files with 205 additions and 155 deletions
+59 -90
View File
@@ -8,6 +8,7 @@ from django.http import HttpResponse, HttpResponseRedirect
from django.core.mail import send_mail
from django.conf import settings
from django.utils.translation import ugettext as _
from django.forms.models import model_to_dict
# Email validation
from django.db.models.signals import post_save
@@ -27,13 +28,18 @@ import requests
import logging
import html
import csv
import pickle
from smtplib import SMTPAuthenticationError
from members.models import Member, Request, Payment, MemberConflict
from members.forms import MemberForm, PaymentForm, ApplicationForm
from members.forms import MemberForm, PaymentForm, ApplicationForm, CSVValidationError
from members.tables import MemberTable, PaymentTable, RequestTable
def error_view(request, message):
return render(request, 'error.html', {'error': str(message)})
def validate_recaptcha(response):
"""
Recaptcha is used in member applications.
@@ -518,23 +524,63 @@ def import_csv(request, *args, **kwargs):
"""Get csv data imported to page and create members based on that."""
try:
data = request.POST['textfield']
payment_source = request.POST['payment_source']
except:
return render(request,
'error.html',
{'error': _('Missing "textfield" POST request field')})
success = Member.from_csv(data)
if success:
logging.info('Imported CSV data:\n'.format(data))
notification = "{}.".format(
_("Successfully imported multiple members"))
return HttpResponseRedirect(
'/members/list?notification={}'
.format(html.escape(notification)))
else:
return render(request,
'error.html',
{'error': _('Failed to import members')})
try:
result = MemberForm.csv_to_models(data, payment_source=payment_source)
except CSVValidationError as ex:
logging.exception('Model validation error')
return error_view(request, ex.form_errors)
except Exception as ex:
logging.exception('Other error in CSV import')
return error_view(request, ex)
member_table = MemberTable(result.members,
request=request,
exclude=['id', 'options'],
attrs={'class': 'table table-bordered table-hover'})
member_table_html = convert_table_to_html(member_table, request)
payment_table = PaymentTable(result.payments,
request=request,
exclude=['id', 'options'],
attrs={'class': 'table table-bordered table-hover'})
payment_table_html = convert_table_to_html(payment_table, request)
request.session['models'] = result
context = {
'members': member_table_html,
'payments': payment_table_html
}
return render(request, 'member_add_many_confirm.html', context)
@ensure_csrf_cookie
@require_http_methods(["POST"])
@permission_required('members.change_member', login_url='/login')
def add_many_confirm(request, *args, **kwargs):
models = request.session['models']
try:
members, payments = models.members, models.payments
for member in members:
member.save()
for payment in payments:
payment.save()
msg = "Successfully imported {} members and {} payments."
notification = _(msg).format(len(members), len(payments))
return HttpResponseRedirect('/members/list?notification={}'.format(html.escape(notification)))
except Exception as ex:
logging.exception('Failed to save models after "add many."')
return error_view(request, _('Failed to import members'))
@ensure_csrf_cookie
@@ -558,62 +604,6 @@ def export_csv(request, *args, **kwargs):
return response
@ensure_csrf_cookie
@require_http_methods(["GET"])
@permission_required('members.change_member', login_url='/login')
def member_duplicates(request, *args, **kwargs):
"""Check for duplicate members."""
conflicts = MemberConflict.objects.all()
context = {
'conflicts': conflicts
}
return render(request, 'member_duplicates.html', context)
@ensure_csrf_cookie
@require_http_methods(["POST"])
@permission_required('members.change_member', login_url='/login')
def resolve_conflict(request, *args, **kwargs):
"""Resolve duplicate member conflict."""
action = request.POST.get('action', None)
if action not in ['first', 'second', 'both']:
return render(request,
'error.html',
{'error': '{}: {}'.format(('Incorrect action value'),
action)})
id = request.POST.get('id', None)
if id is None:
return render(request,
'error.html',
{'error': '{}: {}'.format(('Incorrect id value'), id)})
conflict = MemberConflict.objects.get(id=id)
first_member = conflict.first_member
second_member = conflict.second_member
if action == 'first':
for payment in second_member.payments.all():
payment.member = first_member
payment.save()
second_member.delete()
elif action == 'second':
for payment in first_member.payments.all():
payment.member = second_member
payment.save()
first_member.delete()
conflict.delete()
if MemberConflict.objects.exists():
return HttpResponseRedirect('/members/duplicates')
else:
notification = _('Successfully resolved all member conflicts.')
return HttpResponseRedirect(
'/members/list?notification={}'.format(html.escape(notification)))
def send_mail_wrapper(subject, message, email_to):
"""Send mail to default email."""
send_mail(subject,
@@ -653,27 +643,6 @@ def email_on_accept(sender, instance, created, **kwargs):
logging.error('Failed to send email to accepted member!')
def check_for_duplicates(instance):
"""Check for member duplicates."""
name_candidates = Member.objects.filter(first_name=instance.first_name,
last_name=instance.last_name)
email_candidates = Member.objects.filter(email=instance.email)
candidates = name_candidates | email_candidates
duplicates = candidates.exclude(id=instance.id)
if len(duplicates) > 0:
conflict = MemberConflict(first_member=instance,
second_member=duplicates[0])
conflict.save()
@receiver(post_save, sender=Member)
def duplicate_receiver(sender, instance, created, **kwargs):
"""Call check_for_duplicates function."""
check_for_duplicates(instance)
# Can be used to retrieve single member information via REST API
class MemberDetail(generics.RetrieveAPIView):
"""Member detail rest API view."""