Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
No results found
Show changes
Commits on Source (8)
Showing with 170 additions and 65 deletions
......@@ -57,8 +57,8 @@ payments.views module
:undoc-members:
:show-inheritance:
payments\.widgets module
------------------------
payments.widgets module
-----------------------
.. automodule:: payments.widgets
:members:
......
......@@ -21,6 +21,7 @@ def send_membership_announcement(dry_run=False):
members = (Member.current_members
.filter(membership__until__isnull=True)
.exclude(membership__type=Membership.HONORARY)
.exclude(email='')
.distinct())
with mail.get_connection() as connection:
......@@ -58,7 +59,7 @@ def send_information_request(dry_run=False):
:param dry_run: does not really send emails if True
"""
members = Member.current_members.all()
members = Member.current_members.all().exclude(email='')
with mail.get_connection() as connection:
for member in members:
......@@ -101,6 +102,7 @@ def send_expiration_announcement(dry_run=False):
members = (Member.current_members
.filter(membership__until__lte=expiry_date)
.exclude(membership__until__isnull=True)
.exclude(email='')
.distinct())
with mail.get_connection() as connection:
......
......@@ -11,6 +11,21 @@ class EmailsTest(TestCase):
@classmethod
def setUpTestData(cls):
cls.member_no_mail = Member.objects.create(
username='no_mail_test',
first_name='Nomail',
last_name='Example'
)
Profile.objects.create(
user=cls.member_no_mail,
language='en',
)
Membership.objects.create(
user=cls.member_no_mail,
type=Membership.MEMBER,
since=timezone.now().replace(year=2017, month=9, day=1),
until=timezone.now().replace(year=2018, month=9, day=1)
)
cls.year_member_nl = Member.objects.create(
username='test1',
first_name='Test1',
......
django.jQuery(function () {
var $ = django.jQuery;
$(".payments-row a").click(function(e) {
e.preventDefault();
var type = $(e.target).data('type');
var href = $(e.target).data('href');
var form = $('<form></form>');
form.attr("method", "post");
form.attr("action", href);
var field = $('<input/>');
field.attr("type", "hidden");
field.attr("name", 'type');
field.attr("value", type);
form.append(field);
var csrf = $('<input/>');
csrf.attr("type", "hidden");
csrf.attr("name", 'csrfmiddlewaretoken');
csrf.attr("value", $("input[name='csrfmiddlewaretoken']").val());
form.append(csrf);
$(document.body).append(form);
form.submit();
});
});
......@@ -6,11 +6,16 @@
{% compress css %}<link rel="stylesheet" type="text/x-scss" href="{% static 'admin/payments/css/forms.scss' %}" />{% endcompress %}
{% endblock %}
{% block extrahead %}
{{ block.super }}
<script type="text/javascript" src="{% static 'admin/payments/js/payments.js' %}"></script>
{% endblock %}
{% block submit_buttons_bottom %}
{% if payment %}
<div class="submit-row payments-row">
<a href="{% url 'payments:admin-process' pk=payment.pk type='cash_payment' %}" class="button process">{% trans "Process (cash payment)" %}</a>
<a href="{% url 'payments:admin-process' pk=payment.pk type='card_payment' %}" class="button process">{% trans "Process (card payment)" %}</a>
<a data-href="{% url 'payments:admin-process' pk=payment.pk %}" data-type="cash_payment" class="button process">{% trans "Process (cash payment)" %}</a>
<a data-href="{% url 'payments:admin-process' pk=payment.pk %}" data-type="card_payment" class="button process">{% trans "Process (card payment)" %}</a>
</div>
{% endif %}
......
......@@ -41,16 +41,20 @@ class PaymentAdminViewTest(TestCase):
self.client.force_login(self.user)
def test_permissions(self):
url = '/payment/admin/process/{}/cash_payment/'.format(
url = '/payment/admin/process/{}/'.format(
self.payment.pk)
response = self.client.get(url)
response = self.client.post(url, {
'type': 'cash_payment',
})
self.assertRedirects(response, '/admin/login/?next=%s' % url)
self._give_user_permissions()
url = '/payment/admin/process/{}/cash_payment/'.format(
url = '/payment/admin/process/{}/'.format(
self.payment.pk)
response = self.client.get(url)
response = self.client.post(url, {
'type': 'cash_payment',
})
self.assertRedirects(
response,
'/admin/payments/payment/%s/change/' % self.payment.pk
......@@ -59,7 +63,7 @@ class PaymentAdminViewTest(TestCase):
@mock.patch('django.contrib.messages.error')
@mock.patch('django.contrib.messages.success')
@mock.patch('payments.services.process_payment')
def test_get(self, process_payment, messages_success, messages_error):
def test_post(self, process_payment, messages_success, messages_error):
process_payment.return_value = [self.payment]
payment_qs = Payment.objects.filter(pk=self.payment.pk)
......@@ -69,28 +73,48 @@ class PaymentAdminViewTest(TestCase):
self._give_user_permissions()
type = 'cash_payment'
response = self.client.get('/payment/admin/process/{}/{}/'
.format(self.payment.pk, type))
self.assertEqual(response.status_code, 302)
self.assertEqual(
response.url,
'/admin/payments/payment/%s/change/' % self.payment.pk
)
process_payment.assert_called_once_with(payment_qs, type)
messages_success.assert_called_once_with(
response.wsgi_request, _('Successfully processed %s.') %
model_ngettext(self.payment, 1)
)
process_payment.return_value = []
response = self.client.get('/payment/admin/process/{}/{}/'
.format(self.payment.pk, type))
messages_error.assert_called_once_with(
response.wsgi_request, _('Could not process %s.') %
model_ngettext(self.payment, 1)
)
with self.subTest('Send post without payload'):
response = self.client.post('/payment/admin/process/{}/'
.format(self.payment.pk))
self.assertEqual(response.status_code, 302)
self.assertEqual(
response.url,
'/admin/payments/payment/%s/change/' % self.payment.pk
)
process_payment.assert_not_called()
messages_error.assert_not_called()
messages_success.assert_not_called()
with self.subTest('Send post with successful processing'):
payment_type = 'cash_payment'
response = self.client.post('/payment/admin/process/{}/'
.format(self.payment.pk), {
'type': payment_type,
})
self.assertEqual(response.status_code, 302)
self.assertEqual(
response.url,
'/admin/payments/payment/%s/change/' % self.payment.pk
)
process_payment.assert_called_once_with(payment_qs, payment_type)
messages_success.assert_called_once_with(
response.wsgi_request, _('Successfully processed %s.') %
model_ngettext(self.payment, 1)
)
with self.subTest('Send post with failed processing'):
process_payment.return_value = []
response = self.client.post('/payment/admin/process/{}/'
.format(self.payment.pk), {
'type': payment_type,
})
messages_error.assert_called_once_with(
response.wsgi_request, _('Could not process %s.') %
model_ngettext(self.payment, 1)
)
......@@ -6,6 +6,6 @@ from .views import PaymentAdminView
app_name = 'payments'
urlpatterns = [
path('admin/process/<uuid:pk>/<type>/',
path('admin/process/<uuid:pk>/',
PaymentAdminView.as_view(), name='admin-process'),
]
......@@ -19,10 +19,14 @@ class PaymentAdminView(View):
"""
View that processes a payment
"""
def get(self, request, *args, **kwargs):
def post(self, request, *args, **kwargs):
payment = Payment.objects.filter(pk=kwargs['pk'])
if not ('type' in request.POST):
return redirect('admin:payments_payment_change', kwargs['pk'])
result = services.process_payment(
payment, kwargs['type']
payment, request.POST['type']
)
if len(result) > 0:
......
function confirmRegChange(e) {
var confirmTxt = gettext("Are you sure you want to excecute this action? Be warned that this doesn't save the form.");
return confirm(confirmTxt);
}
django.jQuery(function () {
var $ = django.jQuery;
$(".registrations-row a").click(function(e) {
e.preventDefault();
var confirmTxt = gettext("Are you sure you want to excecute this action? Be warned that this doesn't save the form.");
var didConfirm = confirm(confirmTxt);
if(didConfirm) {
var action = $(e.target).data('action');
var href = $(e.target).data('href');
var form = $('<form></form>');
form.attr("method", "post");
form.attr("action", href);
var field = $('<input/>');
field.attr("type", "hidden");
field.attr("name", 'action');
field.attr("value", action);
form.append(field);
var csrf = $('<input/>');
csrf.attr("type", "hidden");
csrf.attr("name", 'csrfmiddlewaretoken');
csrf.attr("value", $("input[name='csrfmiddlewaretoken']").val());
form.append(csrf);
$(document.body).append(form);
form.submit();
}
return false;
});
});
......@@ -14,8 +14,8 @@
{% block submit_buttons_bottom %}
{% if entry %}
<div class="submit-row registrations-row">
<a href="{% url 'registrations:admin-accept' pk=entry.pk %}" class="button accept" onclick="return confirmRegChange();">{% trans "Accept" %}</a>
<a href="{% url 'registrations:admin-reject' pk=entry.pk %}" class="button reject" onclick="return confirmRegChange()">{% trans "Reject" %}</a>
<a data-href="{% url 'registrations:admin-process' pk=entry.pk %}" class="button accept" data-action="accept">{% trans "Accept" %}</a>
<a data-href="{% url 'registrations:admin-process' pk=entry.pk %}" class="button reject" data-action="reject">{% trans "Reject" %}</a>
</div>
{% endif %}
......
......@@ -90,14 +90,14 @@ class EntryAdminViewTest(TestCase):
self.client.force_login(self.user)
def test_permissions(self):
url = '/registration/admin/accept/{}/'.format(self.entry1.pk)
response = self.client.get(url)
url = '/registration/admin/process/{}/'.format(self.entry1.pk)
response = self.client.post(url)
self.assertRedirects(response, '/admin/login/?next=%s' % url)
self._give_user_permissions()
url = '/registration/admin/accept/{}/'.format(self.entry1.pk)
response = self.client.get(url)
url = '/registration/admin/process/{}/'.format(self.entry1.pk)
response = self.client.post(url)
self.assertRedirects(
response,
'/admin/registrations/registration/%s/change/' % self.entry1.pk
......@@ -126,7 +126,10 @@ class EntryAdminViewTest(TestCase):
qs_mock.get = Mock(return_value=entry_qs.get())
request = _get_mock_request()
response = self.view.get(request, pk=entry.pk)
request.POST = {
'action': 'accept',
}
response = self.view.post(request, pk=entry.pk)
self.assertEqual(response.status_code, 302)
self.assertEqual(
......@@ -142,7 +145,7 @@ class EntryAdminViewTest(TestCase):
model_ngettext(entry_qs.all()[0], 1), '')
accept_entries.return_value = 0
self.view.get(request, pk=entry.pk)
self.view.post(request, pk=entry.pk)
request._messages.add.assert_any_call(
messages.ERROR, _('Could not accept %s.') %
......@@ -150,7 +153,7 @@ class EntryAdminViewTest(TestCase):
accept_entries.return_value = 1
check_unique_user.return_value = False
self.view.get(request, pk=entry.pk)
self.view.post(request, pk=entry.pk)
request._messages.add.assert_any_call(
messages.ERROR, _('Could not accept %s. '
......@@ -176,7 +179,10 @@ class EntryAdminViewTest(TestCase):
qs_mock.get = Mock(return_value=entry_qs.get())
request = _get_mock_request()
response = self.view.get(request, pk=entry.pk)
request.POST = {
'action': 'reject',
}
response = self.view.post(request, pk=entry.pk)
self.assertEqual(response.status_code, 302)
......@@ -193,7 +199,7 @@ class EntryAdminViewTest(TestCase):
model_ngettext(entry_qs.all()[0], 1), '')
reject_entries.return_value = 0
self.view.get(request, pk=entry.pk)
self.view.post(request, pk=entry.pk)
request._messages.add.assert_any_call(
messages.ERROR, _('Could not reject %s.') %
......@@ -209,7 +215,7 @@ class EntryAdminViewTest(TestCase):
)
request = _get_mock_request()
response = self.view.get(request, pk=4)
response = self.view.post(request, pk=4)
self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, reverse('admin:index'))
......@@ -233,7 +239,7 @@ class EntryAdminViewTest(TestCase):
qs_mock.get = Mock(return_value=entry_qs.get())
request = _get_mock_request()
response = self.view.get(request, pk=entry.pk)
response = self.view.post(request, pk=entry.pk)
self.assertFalse(reject_entries.called)
self.assertFalse(accept_entries.called)
......
......@@ -18,12 +18,8 @@ urlpatterns = [
path('renew/success/', TemplateView.as_view(
template_name='registrations/renewal_success.html'),
name='renew-success'),
path('admin/accept/<uuid:pk>/',
EntryAdminView.as_view(action='accept'),
name='admin-accept'),
path('admin/reject/<uuid:pk>/',
EntryAdminView.as_view(action='reject'),
name='admin-reject'),
path('admin/process/<uuid:pk>/', EntryAdminView.as_view(),
name='admin-process'),
path('confirm-email/<uuid:pk>/',
ConfirmEmailView.as_view(), name='confirm-email'),
]
......@@ -42,16 +42,16 @@ class EntryAdminView(View):
"""
View that handles the review processing of entries
"""
action = None
def get(self, request, *args, **kwargs):
def post(self, request, *args, **kwargs):
action = request.POST.get('action')
entry_qs = Entry.objects.filter(pk=kwargs['pk'])
try:
entry = entry_qs.get()
except Entry.DoesNotExist:
return redirect('admin:index')
if self.action == 'accept':
if action == 'accept':
if not services.check_unique_user(entry):
messages.error(request, _('Could not accept %s. '
'Username is not unique.') %
......@@ -62,7 +62,7 @@ class EntryAdminView(View):
else:
messages.error(request, _('Could not accept %s.') %
model_ngettext(entry, 1))
elif self.action == 'reject':
elif action == 'reject':
if services.reject_entries(entry_qs) > 0:
messages.success(request, _('Successfully rejected %s.') %
model_ngettext(entry, 1))
......