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