From 5aba93c8152bd602e659b4cfb2a2ad30555571a0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Mon, 23 May 2022 09:57:50 +0200
Subject: [PATCH 2/3] pricing: check-type views (#65459)

---
 lingo/pricing/forms.py                        |  26 +++
 .../lingo/pricing/manager_agenda_list.html    |   1 +
 .../pricing/manager_check_type_form.html      |  31 +++
 .../manager_check_type_group_form.html        |  31 +++
 .../pricing/manager_check_type_list.html      |  59 ++++++
 lingo/pricing/urls.py                         |  38 ++++
 lingo/pricing/views.py                        | 127 +++++++++++-
 tests/pricing/manager/test_checktype.py       | 190 ++++++++++++++++++
 8 files changed, 502 insertions(+), 1 deletion(-)
 create mode 100644 lingo/pricing/templates/lingo/pricing/manager_check_type_form.html
 create mode 100644 lingo/pricing/templates/lingo/pricing/manager_check_type_group_form.html
 create mode 100644 lingo/pricing/templates/lingo/pricing/manager_check_type_list.html
 create mode 100644 tests/pricing/manager/test_checktype.py

diff --git a/lingo/pricing/forms.py b/lingo/pricing/forms.py
index 8f26b6c..3f1a750 100644
--- a/lingo/pricing/forms.py
+++ b/lingo/pricing/forms.py
@@ -19,6 +19,7 @@ from django.forms import ValidationError
 from django.template import Template, TemplateSyntaxError
 from django.utils.translation import ugettext_lazy as _
 
+from lingo.agendas.models import CheckType
 from lingo.pricing.models import AgendaPricing, Criteria, CriteriaCategory
 
 
@@ -138,3 +139,28 @@ class PricingMatrixForm(forms.Form):
         super().__init__(*args, **kwargs)
         for i in range(len(matrix.rows[0].cells)):
             self.fields['crit_%i' % i] = forms.DecimalField(required=True, max_digits=5, decimal_places=2)
+
+
+class NewCheckTypeForm(forms.ModelForm):
+    class Meta:
+        model = CheckType
+        fields = ['label', 'kind', 'pricing', 'pricing_rate']
+
+    def clean(self):
+        super().clean()
+        if self.cleaned_data.get('pricing') is not None and self.cleaned_data.get('pricing_rate') is not None:
+            raise ValidationError(_('Please choose between pricing and pricing rate.'))
+
+
+class CheckTypeForm(NewCheckTypeForm):
+    class Meta:
+        model = CheckType
+        fields = ['label', 'slug', 'pricing', 'pricing_rate', 'disabled']
+
+    def clean_slug(self):
+        slug = self.cleaned_data['slug']
+
+        if self.instance.group.check_types.filter(slug=slug).exclude(pk=self.instance.pk).exists():
+            raise ValidationError(_('Another check type exists with the same identifier.'))
+
+        return slug
diff --git a/lingo/pricing/templates/lingo/pricing/manager_agenda_list.html b/lingo/pricing/templates/lingo/pricing/manager_agenda_list.html
index 0790d63..d9bd72d 100644
--- a/lingo/pricing/templates/lingo/pricing/manager_agenda_list.html
+++ b/lingo/pricing/templates/lingo/pricing/manager_agenda_list.html
@@ -10,6 +10,7 @@
 <h2>{% trans 'Agendas' %}</h2>
 <span class="actions">
   <a href="{% url 'lingo-manager-agenda-sync' %}">{% trans 'Refresh agendas' %}</a>
+  <a href="{% url 'lingo-manager-check-type-list' %}">{% trans 'Check types' %}</a>
 </span>
 {% endblock %}
 
diff --git a/lingo/pricing/templates/lingo/pricing/manager_check_type_form.html b/lingo/pricing/templates/lingo/pricing/manager_check_type_form.html
new file mode 100644
index 0000000..671e83d
--- /dev/null
+++ b/lingo/pricing/templates/lingo/pricing/manager_check_type_form.html
@@ -0,0 +1,31 @@
+{% extends "lingo/pricing/manager_check_type_list.html" %}
+{% load i18n %}
+
+{% block breadcrumb %}
+{{ block.super }}
+{% if form.instance.pk %}
+<a href="{% url 'lingo-manager-check-type-edit' form.instance.group_id form.instance.pk %}">{{ form.instance }}</a>
+{% else %}
+<a href="{% url 'lingo-manager-check-type-add' form.instance.group_id %}">{% trans "New check type" %}</a>
+{% endif %}
+{% endblock %}
+
+{% block appbar %}
+{% if form.instance.pk %}
+<h2>{{ form.instance.group }} - {% trans "Edit check type" %}</h2>
+{% else %}
+<h2>{{ form.instance.group }} - {% trans "New check type" %}</h2>
+{% endif %}
+{% endblock %}
+
+{% block content %}
+
+<form method="post" enctype="multipart/form-data">
+  {% csrf_token %}
+  {{ form.as_p }}
+  <div class="buttons">
+    <button class="submit-button">{% trans "Save" %}</button>
+    <a class="cancel" href="{% url 'lingo-manager-check-type-list' %}">{% trans 'Cancel' %}</a>
+  </div>
+</form>
+{% endblock %}
diff --git a/lingo/pricing/templates/lingo/pricing/manager_check_type_group_form.html b/lingo/pricing/templates/lingo/pricing/manager_check_type_group_form.html
new file mode 100644
index 0000000..6730cce
--- /dev/null
+++ b/lingo/pricing/templates/lingo/pricing/manager_check_type_group_form.html
@@ -0,0 +1,31 @@
+{% extends "lingo/pricing/manager_check_type_list.html" %}
+{% load i18n %}
+
+{% block breadcrumb %}
+{{ block.super }}
+{% if object.pk %}
+<a href="{% url 'lingo-manager-check-type-group-edit' object.pk %}">{{ object }}</a>
+{% else %}
+<a href="{% url 'lingo-manager-check-type-group-add' %}">{% trans "New check type group" %}</a>
+{% endif %}
+{% endblock %}
+
+{% block appbar %}
+{% if object.pk %}
+<h2>{% trans "Edit check type group" %}</h2>
+{% else %}
+<h2>{% trans "New check type group" %}</h2>
+{% endif %}
+{% endblock %}
+
+{% block content %}
+
+<form method="post" enctype="multipart/form-data">
+  {% csrf_token %}
+  {{ form.as_p }}
+  <div class="buttons">
+    <button class="submit-button">{% trans "Save" %}</button>
+    <a class="cancel" href="{% url 'lingo-manager-check-type-list' %}">{% trans 'Cancel' %}</a>
+  </div>
+</form>
+{% endblock %}
diff --git a/lingo/pricing/templates/lingo/pricing/manager_check_type_list.html b/lingo/pricing/templates/lingo/pricing/manager_check_type_list.html
new file mode 100644
index 0000000..61effaa
--- /dev/null
+++ b/lingo/pricing/templates/lingo/pricing/manager_check_type_list.html
@@ -0,0 +1,59 @@
+{% extends "lingo/pricing/manager_agenda_list.html" %}
+{% load i18n %}
+
+{% block breadcrumb %}
+{{ block.super }}
+<a href="{% url 'lingo-manager-check-type-list' %}">{% trans "Check types" %}</a>
+{% endblock %}
+
+{% block appbar %}
+<h2>{% trans 'Check types' %}</h2>
+<span class="actions">
+<a rel="popup" href="{% url 'lingo-manager-check-type-group-add' %}">{% trans 'New group' %}</a>
+</span>
+{% endblock %}
+
+{% block content %}
+<div class="pk-information">
+<p>{% trans "Define here check types used in events agendas to check bookings." %}</p>
+</div>
+{% for object in object_list %}
+<div class="section check-type-group">
+    <h3>
+    <a rel="popup" href="{% url 'lingo-manager-check-type-group-edit' object.pk %}">{{ object }}</a>
+    <span>
+    <a class="button" href="{% url 'lingo-manager-check-type-group-export' object.pk %}">{% trans "Export"%}</a>
+    <a class="button" rel="popup" href="{% url 'lingo-manager-check-type-group-delete' object.pk %}">{% trans "Delete"%}</a>
+    </span>
+    </h3>
+  <div>
+  <ul class="objects-list single-links">
+    {% for check_type in object.check_types.all %}
+    {% if check_type.kind == 'absence' %}
+    <li>
+        <a rel="popup" href="{% url 'lingo-manager-check-type-edit' object.pk check_type.pk %}">{% trans "Absence" %} - {{ check_type }}{% if check_type.pricing %}{% endif %}{% if check_type.disabled %}<span class="extra-info"> ({% trans "disabled" %})</span>{% endif %}</a>
+        <a class="delete" rel="popup" href="{% url 'lingo-manager-check-type-delete' object.pk check_type.pk %}">{% trans "delete"%}</a>
+    </li>
+    {% endif %}
+    {% endfor %}
+    {% for check_type in object.check_types.all %}
+    {% if check_type.kind == 'presence' %}
+    <li>
+        <a rel="popup" href="{% url 'lingo-manager-check-type-edit' object.pk check_type.pk %}">{% trans "Presence" %} - {{ check_type }}{% if check_type.disabled %}<span class="extra-info"> ({% trans "disabled" %})</span>{% endif %}</a>
+        <a class="delete" rel="popup" href="{% url 'lingo-manager-check-type-delete' object.pk check_type.pk %}">{% trans "delete"%}</a>
+    </li>
+    {% endif %}
+    {% endfor %}
+    <li><a class="add" rel="popup" href="{% url 'lingo-manager-check-type-add' object.pk %}">{% trans "Add a check type" %}</a></li>
+  </ul>
+  </div>
+</div>
+{% empty %}
+<div class="big-msg-info">
+  {% blocktrans %}
+  This site doesn't have any check type group yet. Click on the "New group" button in the top
+  right of the page to add a first one.
+  {% endblocktrans %}
+</div>
+{% endfor %}
+{% endblock %}
diff --git a/lingo/pricing/urls.py b/lingo/pricing/urls.py
index 95b64c9..a8a6b39 100644
--- a/lingo/pricing/urls.py
+++ b/lingo/pricing/urls.py
@@ -173,4 +173,42 @@ urlpatterns = [
         staff_member_required(views.agenda_pricing_matrix_edit),
         name='lingo-manager-agenda-pricing-matrix-slug-edit',
     ),
+    url(
+        r'^check-types/$', staff_member_required(views.check_type_list), name='lingo-manager-check-type-list'
+    ),
+    url(
+        r'^check-type/group/add/$',
+        staff_member_required(views.check_type_group_add),
+        name='lingo-manager-check-type-group-add',
+    ),
+    url(
+        r'^check-type/group/(?P<pk>\d+)/edit/$',
+        staff_member_required(views.check_type_group_edit),
+        name='lingo-manager-check-type-group-edit',
+    ),
+    url(
+        r'^check-type/group/(?P<pk>\d+)/delete/$',
+        staff_member_required(views.check_type_group_delete),
+        name='lingo-manager-check-type-group-delete',
+    ),
+    url(
+        r'^check-type/group/(?P<pk>\d+)/export/$',
+        staff_member_required(views.check_type_group_export),
+        name='lingo-manager-check-type-group-export',
+    ),
+    url(
+        r'^check-type/group/(?P<group_pk>\d+)/add/$',
+        staff_member_required(views.check_type_add),
+        name='lingo-manager-check-type-add',
+    ),
+    url(
+        r'^check-type/group/(?P<group_pk>\d+)/(?P<pk>\d+)/edit/$',
+        staff_member_required(views.check_type_edit),
+        name='lingo-manager-check-type-edit',
+    ),
+    url(
+        r'^check-type/group/(?P<group_pk>\d+)/(?P<pk>\d+)/delete/$',
+        staff_member_required(views.check_type_delete),
+        name='lingo-manager-check-type-delete',
+    ),
 ]
diff --git a/lingo/pricing/views.py b/lingo/pricing/views.py
index a75ebf2..7c175b6 100644
--- a/lingo/pricing/views.py
+++ b/lingo/pricing/views.py
@@ -40,13 +40,15 @@ from django.views.generic import (
 from django.views.generic.detail import SingleObjectMixin
 
 from lingo.agendas.chrono import refresh_agendas
-from lingo.agendas.models import Agenda
+from lingo.agendas.models import Agenda, CheckType, CheckTypeGroup
 from lingo.agendas.views import AgendaMixin
 from lingo.pricing.forms import (
     AgendaPricingForm,
+    CheckTypeForm,
     CriteriaForm,
     ExportForm,
     ImportForm,
+    NewCheckTypeForm,
     NewCriteriaForm,
     PricingCriteriaCategoryAddForm,
     PricingCriteriaCategoryEditForm,
@@ -786,3 +788,126 @@ class AgendaPricingMatrixEdit(AgendaMixin, FormView):
 
 
 agenda_pricing_matrix_edit = AgendaPricingMatrixEdit.as_view()
+
+
+class CheckTypeListView(ListView):
+    template_name = 'lingo/pricing/manager_check_type_list.html'
+    model = CheckTypeGroup
+
+    def get_queryset(self):
+        return CheckTypeGroup.objects.prefetch_related('check_types')
+
+
+check_type_list = CheckTypeListView.as_view()
+
+
+class CheckTypeGroupAddView(CreateView):
+    template_name = 'lingo/pricing/manager_check_type_group_form.html'
+    model = CheckTypeGroup
+    fields = ['label']
+
+    def get_success_url(self):
+        return reverse('lingo-manager-check-type-list')
+
+
+check_type_group_add = CheckTypeGroupAddView.as_view()
+
+
+class CheckTypeGroupEditView(UpdateView):
+    template_name = 'lingo/pricing/manager_check_type_group_form.html'
+    model = CheckTypeGroup
+    fields = ['label', 'slug']
+
+    def get_success_url(self):
+        return reverse('lingo-manager-check-type-list')
+
+
+check_type_group_edit = CheckTypeGroupEditView.as_view()
+
+
+class CheckTypeGroupDeleteView(DeleteView):
+    template_name = 'lingo/manager_confirm_delete.html'
+    model = CheckTypeGroup
+
+    def get_success_url(self):
+        return reverse('lingo-manager-check-type-list')
+
+
+check_type_group_delete = CheckTypeGroupDeleteView.as_view()
+
+
+class CheckTypeGroupExport(DetailView):
+    model = CheckTypeGroup
+
+    def get(self, request, *args, **kwargs):
+        response = HttpResponse(content_type='application/json')
+        today = datetime.date.today()
+        attachment = 'attachment; filename="export_check_type_group_{}_{}.json"'.format(
+            self.get_object().slug, today.strftime('%Y%m%d')
+        )
+        response['Content-Disposition'] = attachment
+        json.dump({'check_type_groups': [self.get_object().export_json()]}, response, indent=2)
+        return response
+
+
+check_type_group_export = CheckTypeGroupExport.as_view()
+
+
+class CheckTypeAddView(CreateView):
+    template_name = 'lingo/pricing/manager_check_type_form.html'
+    model = CheckType
+    form_class = NewCheckTypeForm
+
+    def dispatch(self, request, *args, **kwargs):
+        self.group_pk = kwargs.pop('group_pk')
+        return super().dispatch(request, *args, **kwargs)
+
+    def get_form_kwargs(self):
+        kwargs = super().get_form_kwargs()
+        if not kwargs.get('instance'):
+            kwargs['instance'] = self.model()
+        kwargs['instance'].group_id = self.group_pk
+        return kwargs
+
+    def get_success_url(self):
+        return reverse('lingo-manager-check-type-list')
+
+
+check_type_add = CheckTypeAddView.as_view()
+
+
+class CheckTypeEditView(UpdateView):
+    template_name = 'lingo/pricing/manager_check_type_form.html'
+    model = CheckType
+    form_class = CheckTypeForm
+
+    def dispatch(self, request, *args, **kwargs):
+        self.group_pk = kwargs.pop('group_pk')
+        return super().dispatch(request, *args, **kwargs)
+
+    def get_queryset(self):
+        return CheckType.objects.filter(group=self.group_pk)
+
+    def get_success_url(self):
+        return reverse('lingo-manager-check-type-list')
+
+
+check_type_edit = CheckTypeEditView.as_view()
+
+
+class CheckTypeDeleteView(DeleteView):
+    template_name = 'lingo/manager_confirm_delete.html'
+    model = CheckType
+
+    def dispatch(self, request, *args, **kwargs):
+        self.group_pk = kwargs.pop('group_pk')
+        return super().dispatch(request, *args, **kwargs)
+
+    def get_queryset(self):
+        return CheckType.objects.filter(group=self.group_pk)
+
+    def get_success_url(self):
+        return reverse('lingo-manager-check-type-list')
+
+
+check_type_delete = CheckTypeDeleteView.as_view()
diff --git a/tests/pricing/manager/test_checktype.py b/tests/pricing/manager/test_checktype.py
new file mode 100644
index 0000000..d442030
--- /dev/null
+++ b/tests/pricing/manager/test_checktype.py
@@ -0,0 +1,190 @@
+import pytest
+
+from lingo.agendas.models import CheckType, CheckTypeGroup
+from tests.utils import login
+
+pytestmark = pytest.mark.django_db
+
+
+def test_add_group(app, admin_user):
+    app = login(app)
+    resp = app.get('/manage/pricing/agendas/')
+    resp = resp.click('Check types')
+    resp = resp.click('New group')
+    resp.form['label'] = 'Foo bar'
+    resp = resp.form.submit()
+    group = CheckTypeGroup.objects.latest('pk')
+    assert resp.location.endswith('/manage/pricing/check-types/')
+    assert group.label == 'Foo bar'
+    assert group.slug == 'foo-bar'
+
+
+def test_edit_group(app, admin_user):
+    group = CheckTypeGroup.objects.create(label='Foo bar')
+    group2 = CheckTypeGroup.objects.create(label='baz')
+
+    app = login(app)
+    resp = app.get('/manage/pricing/check-types/')
+    resp = resp.click(href='/manage/pricing/check-type/group/%s/edit/' % group.pk)
+    resp.form['label'] = 'Foo bar baz'
+    resp.form['slug'] = group2.slug
+    resp = resp.form.submit()
+    assert resp.context['form'].errors['slug'] == ['Check type group with this Identifier already exists.']
+
+    resp.form['slug'] = 'baz2'
+    resp = resp.form.submit()
+    assert resp.location.endswith('/manage/pricing/check-types/')
+    group.refresh_from_db()
+    assert group.label == 'Foo bar baz'
+    assert group.slug == 'baz2'
+
+
+def test_delete_group(app, admin_user):
+    group = CheckTypeGroup.objects.create(label='Foo bar')
+    CheckType.objects.create(label='Foo reason', group=group)
+
+    app = login(app)
+    resp = app.get('/manage/pricing/check-types/')
+    resp = resp.click(href='/manage/pricing/check-type/group/%s/delete/' % group.pk)
+    resp = resp.form.submit()
+    assert resp.location.endswith('/manage/pricing/check-types/')
+    assert CheckTypeGroup.objects.exists() is False
+    assert CheckType.objects.exists() is False
+
+
+def test_add_check_type(app, admin_user):
+    group = CheckTypeGroup.objects.create(label='Foo bar')
+
+    app = login(app)
+    resp = app.get('/manage/pricing/check-types/')
+    resp = resp.click('Add a check type')
+    resp.form['label'] = 'Foo reason'
+    assert 'slug' not in resp.context['form'].fields
+    assert 'disabled' not in resp.context['form'].fields
+    resp = resp.form.submit()
+    check_type = CheckType.objects.latest('pk')
+    assert resp.location.endswith('/manage/pricing/check-types/')
+    assert check_type.label == 'Foo reason'
+    assert check_type.group == group
+    assert check_type.slug == 'foo-reason'
+    assert check_type.kind == 'absence'
+    assert check_type.pricing is None
+    assert check_type.pricing_rate is None
+
+    resp = app.get('/manage/pricing/check-type/group/%s/add/' % group.pk)
+    resp.form['label'] = 'Foo reason'
+    resp.form['kind'] = 'presence'
+    resp = resp.form.submit()
+    assert resp.location.endswith('/manage/pricing/check-types/')
+    check_type = CheckType.objects.latest('pk')
+    assert check_type.label == 'Foo reason'
+    assert check_type.slug == 'foo-reason-1'
+    assert check_type.kind == 'presence'
+
+
+def test_add_check_type_pricing(app, admin_user):
+    group = CheckTypeGroup.objects.create(label='Foo bar')
+
+    app = login(app)
+    resp = app.get('/manage/pricing/check-type/group/%s/add/' % group.pk)
+    assert 'pricing' in resp.context['form'].fields
+    assert 'pricing_rate' in resp.context['form'].fields
+    resp.form['label'] = 'Foo reason'
+    resp.form['pricing'] = 42
+    resp.form['pricing_rate'] = 150
+    resp = resp.form.submit()
+    assert resp.context['form'].errors['__all__'] == ['Please choose between pricing and pricing rate.']
+    resp.form['pricing'] = 0
+    resp.form['pricing_rate'] = 0
+    resp = resp.form.submit()
+    assert resp.context['form'].errors['__all__'] == ['Please choose between pricing and pricing rate.']
+    resp.form['pricing'] = 42
+    resp.form['pricing_rate'] = None
+    resp = resp.form.submit()
+    check_type = CheckType.objects.latest('pk')
+    assert check_type.pricing == 42
+    assert check_type.pricing_rate is None
+
+    resp = app.get('/manage/pricing/check-type/group/%s/add/' % group.pk)
+    resp.form['label'] = 'Foo reason'
+    resp.form['pricing_rate'] = 150
+    resp = resp.form.submit()
+    check_type = CheckType.objects.latest('pk')
+    assert check_type.pricing is None
+    assert check_type.pricing_rate == 150
+
+
+def test_edit_check_type(app, admin_user):
+    group = CheckTypeGroup.objects.create(label='Foo bar')
+    check_type = CheckType.objects.create(label='Foo reason', group=group, kind='presence')
+    check_type2 = CheckType.objects.create(label='Baz', group=group)
+    group2 = CheckTypeGroup.objects.create(label='Foo bar')
+    check_type3 = CheckType.objects.create(label='Foo bar reason', group=group2)
+
+    app = login(app)
+    resp = app.get('/manage/pricing/check-types/')
+    resp = resp.click(href='/manage/pricing/check-type/group/%s/%s/edit/' % (group.pk, check_type.pk))
+    assert 'This check type is set on some existing bookings, modify it with caution.' not in resp
+    resp.form['label'] = 'Foo bar reason'
+    resp.form['slug'] = check_type2.slug
+    resp.form['disabled'] = True
+    assert 'kind' not in resp.context['form'].fields
+    resp = resp.form.submit()
+    assert resp.context['form'].errors['slug'] == ['Another check type exists with the same identifier.']
+
+    resp.form['slug'] = check_type3.slug
+    resp = resp.form.submit()
+    assert resp.location.endswith('/manage/pricing/check-types/')
+    check_type.refresh_from_db()
+    assert check_type.label == 'Foo bar reason'
+    assert check_type.slug == 'foo-bar-reason'
+    assert check_type.kind == 'presence'
+    assert check_type.pricing is None
+    assert check_type.pricing_rate is None
+    assert check_type.disabled is True
+
+    app.get('/manage/pricing/check-type/group/%s/%s/edit/' % (group2.pk, check_type.pk), status=404)
+
+
+def test_edit_check_type_pricing(app, admin_user):
+    group = CheckTypeGroup.objects.create(label='Foo bar')
+    check_type = CheckType.objects.create(label='Foo reason', group=group)
+
+    app = login(app)
+    resp = app.get('/manage/pricing/check-type/group/%s/%s/edit/' % (group.pk, check_type.pk))
+    assert 'pricing' in resp.context['form'].fields
+    assert 'pricing_rate' in resp.context['form'].fields
+    resp.form['pricing'] = 42
+    resp.form['pricing_rate'] = 150
+    resp = resp.form.submit()
+    assert resp.context['form'].errors['__all__'] == ['Please choose between pricing and pricing rate.']
+    resp.form['pricing'] = 42
+    resp.form['pricing_rate'] = None
+    resp = resp.form.submit()
+    check_type.refresh_from_db()
+    assert check_type.pricing == 42
+    assert check_type.pricing_rate is None
+
+    resp = app.get('/manage/pricing/check-type/group/%s/%s/edit/' % (group.pk, check_type.pk))
+    resp.form['pricing'] = None
+    resp.form['pricing_rate'] = 150
+    resp = resp.form.submit()
+    check_type.refresh_from_db()
+    assert check_type.pricing is None
+    assert check_type.pricing_rate == 150
+
+
+def test_delete_check_type(app, admin_user):
+    group = CheckTypeGroup.objects.create(label='Foo bar')
+    check_type = CheckType.objects.create(label='Foo reason', group=group)
+
+    app = login(app)
+    resp = app.get('/manage/pricing/check-types/')
+    resp = resp.click(href='/manage/pricing/check-type/group/%s/%s/delete/' % (group.pk, check_type.pk))
+    resp = resp.form.submit()
+    assert resp.location.endswith('/manage/pricing/check-types/')
+    assert CheckTypeGroup.objects.exists() is True
+    assert CheckType.objects.exists() is False
+
+    group2 = CheckTypeGroup.objects.create(label='Foo bar baz')
+    app.get('/manage/pricing/check-type/group/%s/%s/delete/' % (group2.pk, check_type.pk), status=404)
-- 
2.35.1

