From 50cceacf894cba7e17d36dd6c40ac20f3f323f28 Mon Sep 17 00:00:00 2001
From: Emmanuel Cazenave <ecazenave@entrouvert.com>
Date: Fri, 16 Sep 2022 17:16:27 +0200
Subject: [PATCH] start invoicing app (#65359)

---
 lingo/invoicing/__init__.py                   |   0
 lingo/invoicing/migrations/0001_initial.py    |  48 ++++++
 lingo/invoicing/migrations/__init__.py        |   0
 lingo/invoicing/models.py                     |  54 +++++++
 .../lingo/invoicing/manager_home.html         |  22 +++
 .../lingo/invoicing/manager_regie_common.html |  12 ++
 .../lingo/invoicing/manager_regie_detail.html |  28 ++++
 .../lingo/invoicing/manager_regie_form.html   |  31 ++++
 .../lingo/invoicing/manager_regie_list.html   |  34 +++++
 lingo/invoicing/urls.py                       |  44 ++++++
 lingo/invoicing/views.py                      |  83 ++++++++++
 .../templates/lingo/manager_homepage.html     |   1 +
 lingo/settings.py                             |   1 +
 lingo/urls.py                                 |   2 +
 tests/invoicing/test_manager.py               | 144 ++++++++++++++++++
 15 files changed, 504 insertions(+)
 create mode 100644 lingo/invoicing/__init__.py
 create mode 100644 lingo/invoicing/migrations/0001_initial.py
 create mode 100644 lingo/invoicing/migrations/__init__.py
 create mode 100644 lingo/invoicing/models.py
 create mode 100644 lingo/invoicing/templates/lingo/invoicing/manager_home.html
 create mode 100644 lingo/invoicing/templates/lingo/invoicing/manager_regie_common.html
 create mode 100644 lingo/invoicing/templates/lingo/invoicing/manager_regie_detail.html
 create mode 100644 lingo/invoicing/templates/lingo/invoicing/manager_regie_form.html
 create mode 100644 lingo/invoicing/templates/lingo/invoicing/manager_regie_list.html
 create mode 100644 lingo/invoicing/urls.py
 create mode 100644 lingo/invoicing/views.py
 create mode 100644 tests/invoicing/test_manager.py

diff --git a/lingo/invoicing/__init__.py b/lingo/invoicing/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/lingo/invoicing/migrations/0001_initial.py b/lingo/invoicing/migrations/0001_initial.py
new file mode 100644
index 0000000..3c377b1
--- /dev/null
+++ b/lingo/invoicing/migrations/0001_initial.py
@@ -0,0 +1,48 @@
+# Generated by Django 2.2.26 on 2022-09-16 13:03
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        ('auth', '0011_update_proxy_permissions'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Regie',
+            fields=[
+                (
+                    'id',
+                    models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+                ),
+                ('label', models.CharField(max_length=150, verbose_name='Label')),
+                ('slug', models.SlugField(max_length=160, unique=True, verbose_name='Identifier')),
+                (
+                    'description',
+                    models.TextField(
+                        blank=True,
+                        help_text='Optional regie description.',
+                        null=True,
+                        verbose_name='Description',
+                    ),
+                ),
+                (
+                    'edit_role',
+                    models.ForeignKey(
+                        blank=True,
+                        default=None,
+                        null=True,
+                        on_delete=django.db.models.deletion.SET_NULL,
+                        related_name='+',
+                        to='auth.Group',
+                        verbose_name='Edit Role',
+                    ),
+                ),
+            ],
+        ),
+    ]
diff --git a/lingo/invoicing/migrations/__init__.py b/lingo/invoicing/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/lingo/invoicing/models.py b/lingo/invoicing/models.py
new file mode 100644
index 0000000..957b644
--- /dev/null
+++ b/lingo/invoicing/models.py
@@ -0,0 +1,54 @@
+# lingo - payment and billing system
+# Copyright (C) 2022  Entr'ouvert
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from django.contrib.auth.models import Group
+from django.db import models
+from django.utils.text import slugify
+from django.utils.translation import gettext_lazy as _
+
+from lingo.utils.misc import generate_slug
+
+
+class Regie(models.Model):
+    label = models.CharField(_('Label'), max_length=150)
+    slug = models.SlugField(_('Identifier'), max_length=160, unique=True)
+    description = models.TextField(
+        _('Description'), null=True, blank=True, help_text=_('Optional regie description.')
+    )
+    edit_role = models.ForeignKey(
+        Group,
+        blank=True,
+        null=True,
+        default=None,
+        related_name='+',
+        verbose_name=_('Edit Role'),
+        on_delete=models.SET_NULL,
+    )
+
+    class Meta:
+        ordering = ['label']
+
+    def __str__(self):
+        return self.label
+
+    def save(self, *args, **kwargs):
+        if not self.slug:
+            self.slug = generate_slug(self)
+        super().save(*args, **kwargs)
+
+    @property
+    def base_slug(self):
+        return slugify(self.label)
diff --git a/lingo/invoicing/templates/lingo/invoicing/manager_home.html b/lingo/invoicing/templates/lingo/invoicing/manager_home.html
new file mode 100644
index 0000000..8211e62
--- /dev/null
+++ b/lingo/invoicing/templates/lingo/invoicing/manager_home.html
@@ -0,0 +1,22 @@
+{% extends "lingo/manager_base.html" %}
+{% load i18n %}
+
+{% block breadcrumb %}
+{{ block.super }}
+<a href="{% url 'lingo-manager-invoicing-home' %}">{% trans 'Invoicing' %}</a>
+{% endblock %}
+
+{% block appbar %}
+<h2>{% trans 'Invoicing' %}</h2>
+{% endblock %}
+
+{% block content %}
+<div id="lingo-manager-main">
+  <div class="fx-grid--t3">
+      <a class="button button-paragraph" href="{% url 'lingo-manager-invoicing-regie-list' %}">
+      {% trans "Regies" %}
+      <p>{% trans "Invoicing regies." %}</p>
+    </a>
+  </div>
+</div>
+{% endblock %}
diff --git a/lingo/invoicing/templates/lingo/invoicing/manager_regie_common.html b/lingo/invoicing/templates/lingo/invoicing/manager_regie_common.html
new file mode 100644
index 0000000..04d7fe5
--- /dev/null
+++ b/lingo/invoicing/templates/lingo/invoicing/manager_regie_common.html
@@ -0,0 +1,12 @@
+{% extends "lingo/invoicing/manager_home.html" %}
+{% load i18n %}
+
+{% block appbar %}
+<h2>{% if regie %}{% trans 'Regie' %} - {{regie}} {% else %}{% trans 'Regies' %}{% endif %}</h2>
+{% endblock %}
+
+
+{% block breadcrumb %}
+{{ block.super }}
+<a href="{% url 'lingo-manager-invoicing-regie-list' %}">{% trans "Regies" %}</a>
+{% endblock %}
diff --git a/lingo/invoicing/templates/lingo/invoicing/manager_regie_detail.html b/lingo/invoicing/templates/lingo/invoicing/manager_regie_detail.html
new file mode 100644
index 0000000..bd1f58c
--- /dev/null
+++ b/lingo/invoicing/templates/lingo/invoicing/manager_regie_detail.html
@@ -0,0 +1,28 @@
+{% extends "lingo/invoicing/manager_regie_common.html" %}
+{% load i18n gadjo %}
+
+{% block breadcrumb %}
+  {{ block.super }}
+  <a href="{% url 'lingo-manager-invoicing-regie-detail' regie.pk %}">{{ object }}</a>
+{% endblock %}
+
+{% block appbar %}
+  {{ block.super }}
+  <span class="actions">
+    <a href="{% url 'lingo-manager-invoicing-regie-delete' pk=regie.pk %}" rel="popup">{% trans "Delete" %}</a>
+    <a href="{% url 'lingo-manager-invoicing-regie-edit' pk=regie.pk %}" rel="popup">{% trans "Edit" %}</a>
+  </span>
+  {% endblock %}
+
+{% block content %}
+{% if regie.description %}
+<div class="bo-block">{{regie.description}}</div>
+{% endif %}
+<div class="bo-block">
+  <h3>{% trans "Parameters" %}</h3>
+  <ul>
+    <li>{% trans "slug" %}&nbsp;: {{regie.slug}}</li>
+    <li>{% trans "edit role" %}&nbsp;: {{regie.edit_role}}</li>
+  </ul>
+</div>
+{% endblock %}
diff --git a/lingo/invoicing/templates/lingo/invoicing/manager_regie_form.html b/lingo/invoicing/templates/lingo/invoicing/manager_regie_form.html
new file mode 100644
index 0000000..7ef7919
--- /dev/null
+++ b/lingo/invoicing/templates/lingo/invoicing/manager_regie_form.html
@@ -0,0 +1,31 @@
+{% extends "lingo/invoicing/manager_regie_common.html" %}
+{% load i18n gadjo %}
+
+{% block breadcrumb %}
+  {{ block.super }}
+  {% if object.pk %}
+  <a href="{% url 'lingo-manager-invoicing-regie-detail' regie.pk %}">{{ regie }}</a>
+  <a href="{% url 'lingo-manager-invoicing-regie-edit' regie.pk %}">{% trans "Edit" %}</a>
+  {% else %}
+  <a href="{% url 'lingo-manager-invoicing-regie-add' %}">{% trans "New regie" %}</a>
+  {% endif %}
+{% endblock %}
+
+{% block appbar %}
+{% if regie.pk %}
+<h2>{% trans "Edit regie" %} - {{regie}}</h2>
+{% else %}
+<h2>{% trans "New regie" %}</h2>
+{% endif %}
+{% endblock %}
+  
+{% block content %}
+  <form method="post" enctype="multipart/form-data">
+    {% csrf_token %}
+    {{ form|with_template }}
+    <div class="buttons">
+      <button>{% trans "Submit" %}</button>
+      <a class="cancel" href="{{cancel_url}}">{% trans 'Cancel' %}</a>
+    </div>
+  </form>
+{% endblock %}
diff --git a/lingo/invoicing/templates/lingo/invoicing/manager_regie_list.html b/lingo/invoicing/templates/lingo/invoicing/manager_regie_list.html
new file mode 100644
index 0000000..8c01e85
--- /dev/null
+++ b/lingo/invoicing/templates/lingo/invoicing/manager_regie_list.html
@@ -0,0 +1,34 @@
+{% extends "lingo/invoicing/manager_regie_common.html" %}
+{% load i18n %}
+
+{% block appbar %}
+<h2>{% trans 'Regies' %}</h2>
+<span class="actions">
+  <a rel="popup" href="{% url 'lingo-manager-invoicing-regie-add' %}">{% trans 'New regie' %}</a>
+</span>
+{% endblock %}
+
+{% block content %}
+{% if object_list %}
+<div>
+  <ul class="objects-list single-links">
+    {% for regie in object_list %}
+    <li>
+      <a href="{% url 'lingo-manager-invoicing-regie-detail' pk=regie.pk %}">
+        {{ regie.label }}
+        <span class="extra-info"> [{% trans "identifier:" %} {{ regie.slug }}]</span>
+      </a>
+    </li>
+    {% endfor %}
+  </ul>
+</div>
+{% else %}
+
+<div class="big-msg-info">
+  {% blocktrans %}
+  This site doesn't have any regie yet. Click on the "New" button in the top
+  right of the page to add a first one.
+  {% endblocktrans %}
+</div>
+{% endif %}
+{% endblock %}
diff --git a/lingo/invoicing/urls.py b/lingo/invoicing/urls.py
new file mode 100644
index 0000000..88ed9f7
--- /dev/null
+++ b/lingo/invoicing/urls.py
@@ -0,0 +1,44 @@
+# lingo - payment and billing system
+# Copyright (C) 2022  Entr'ouvert
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from django.conf.urls import url
+
+from . import views
+
+urlpatterns = [
+    url(r'^$', views.home, name='lingo-manager-invoicing-home'),
+    url(r'^regies/$', views.regies_list, name='lingo-manager-invoicing-regie-list'),
+    url(
+        r'^regie/add/$',
+        views.regie_add,
+        name='lingo-manager-invoicing-regie-add',
+    ),
+    url(
+        r'^regie/(?P<pk>\d+)/$',
+        views.regie_detail,
+        name='lingo-manager-invoicing-regie-detail',
+    ),
+    url(
+        r'^regie/(?P<pk>\d+)/edit/$',
+        views.regie_edit,
+        name='lingo-manager-invoicing-regie-edit',
+    ),
+    url(
+        r'^regie/(?P<pk>\d+)/delete/$',
+        views.regie_delete,
+        name='lingo-manager-invoicing-regie-delete',
+    ),
+]
diff --git a/lingo/invoicing/views.py b/lingo/invoicing/views.py
new file mode 100644
index 0000000..461868b
--- /dev/null
+++ b/lingo/invoicing/views.py
@@ -0,0 +1,83 @@
+# lingo - payment and billing system
+# Copyright (C) 2022  Entr'ouvert
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from django.urls import reverse
+from django.views.generic import CreateView, DeleteView, DetailView, ListView, TemplateView, UpdateView
+
+from lingo.invoicing.models import Regie
+
+
+class HomeView(TemplateView):
+    template_name = 'lingo/invoicing/manager_home.html'
+
+
+home = HomeView.as_view()
+
+
+class RegiesListView(ListView):
+    template_name = 'lingo/invoicing/manager_regie_list.html'
+    model = Regie
+
+
+regies_list = RegiesListView.as_view()
+
+
+class RegieAddView(CreateView):
+    template_name = 'lingo/invoicing/manager_regie_form.html'
+    model = Regie
+    fields = ['label', 'description', 'edit_role']
+
+    def get_success_url(self):
+        return reverse('lingo-manager-invoicing-regie-detail', args=[self.object.pk])
+
+
+regie_add = RegieAddView.as_view()
+
+
+class RegieDetailView(DetailView):
+    template_name = 'lingo/invoicing/manager_regie_detail.html'
+    model = Regie
+
+    def get_context_data(self, **kwargs):
+        context = super().get_context_data(**kwargs)
+        context['regie'] = self.object
+        return context
+
+
+regie_detail = RegieDetailView.as_view()
+
+
+class RegieEditView(UpdateView):
+    template_name = 'lingo/invoicing/manager_regie_form.html'
+    model = Regie
+    fields = ['label', 'description', 'edit_role']
+
+    def get_success_url(self):
+        return reverse('lingo-manager-invoicing-regie-detail', args=[self.object.pk])
+
+
+regie_edit = RegieEditView.as_view()
+
+
+class RegieDeleteView(DeleteView):
+    template_name = 'lingo/manager_confirm_delete.html'
+    model = Regie
+
+    def get_success_url(self):
+        return reverse('lingo-manager-invoicing-regie-list')
+
+
+regie_delete = RegieDeleteView.as_view()
diff --git a/lingo/manager/templates/lingo/manager_homepage.html b/lingo/manager/templates/lingo/manager_homepage.html
index 322c304..a721ad4 100644
--- a/lingo/manager/templates/lingo/manager_homepage.html
+++ b/lingo/manager/templates/lingo/manager_homepage.html
@@ -5,5 +5,6 @@
   <h2>{% trans 'Payments' %}</h2>
   <span class="actions">
     <a href="{% url 'lingo-manager-pricing-home' %}">{% trans 'Pricing' context 'pricing' %}</a>
+    <a href="{% url 'lingo-manager-invoicing-home' %}">{% trans 'Invoicing' %}</a>
   </span>
 {% endblock %}
diff --git a/lingo/settings.py b/lingo/settings.py
index 1dae95b..284586e 100644
--- a/lingo/settings.py
+++ b/lingo/settings.py
@@ -57,6 +57,7 @@ INSTALLED_APPS = (
     'rest_framework',
     'lingo.agendas',
     'lingo.api',
+    'lingo.invoicing',
     'lingo.manager',
     'lingo.pricing',
 )
diff --git a/lingo/urls.py b/lingo/urls.py
index af273a2..63cb8c5 100644
--- a/lingo/urls.py
+++ b/lingo/urls.py
@@ -20,6 +20,7 @@ from django.conf.urls.static import static
 from django.contrib.staticfiles.urls import staticfiles_urlpatterns
 
 from .api.urls import urlpatterns as lingo_api_urls
+from .invoicing.urls import urlpatterns as lingo_invoicing_urls
 from .manager.urls import urlpatterns as lingo_manager_urls
 from .pricing.urls import urlpatterns as lingo_pricing_urls
 from .urls_utils import decorated_includes, manager_required
@@ -28,6 +29,7 @@ from .views import homepage, login, logout
 urlpatterns = [
     url(r'^$', homepage, name='homepage'),
     url(r'^manage/', decorated_includes(manager_required, include(lingo_manager_urls))),
+    url(r'^manage/invoicing/', decorated_includes(manager_required, include(lingo_invoicing_urls))),
     url(r'^manage/pricing/', decorated_includes(manager_required, include(lingo_pricing_urls))),
     url(r'^api/', include(lingo_api_urls)),
     url(r'^login/$', login, name='auth_login'),
diff --git a/tests/invoicing/test_manager.py b/tests/invoicing/test_manager.py
new file mode 100644
index 0000000..9574565
--- /dev/null
+++ b/tests/invoicing/test_manager.py
@@ -0,0 +1,144 @@
+from urllib.parse import urlparse
+
+import pytest
+from django.contrib.auth.models import Group
+from django.urls import reverse
+
+from lingo.invoicing.models import Regie
+from tests.utils import login
+
+pytestmark = pytest.mark.django_db
+
+
+def test_manager_home_show_invoicing(app, admin_user):
+    app = login(app)
+    resp = app.get('/manage/')
+    anchor = resp.pyquery('div#appbar span.actions a[href="%s"]' % reverse('lingo-manager-invoicing-home'))
+    assert anchor.text() == 'Invoicing'
+
+
+def test_manager_invoicing_home(app, admin_user):
+    app = login(app)
+    resp = app.get(reverse('lingo-manager-invoicing-home'))
+    h2 = resp.pyquery('div#appbar h2')
+    assert h2.text() == 'Invoicing'
+    anchor = resp.pyquery(
+        'div#lingo-manager-main div a[href="%s"]' % reverse('lingo-manager-invoicing-regie-list')
+    )
+    assert anchor.text().startswith('Regies')
+
+
+def test_manager_invoicing_regie_list_title(app, admin_user):
+    app = login(app)
+    resp = app.get(reverse('lingo-manager-invoicing-regie-list'))
+    h2 = resp.pyquery('div#appbar h2')
+    assert h2.text() == 'Regies'
+
+
+def test_manager_invoicing_regie_list_empty(app, admin_user):
+    app = login(app)
+    resp = app.get(reverse('lingo-manager-invoicing-regie-list'))
+    msg_info = resp.pyquery('div#content div.big-msg-info')
+    assert (
+        msg_info.text()
+        == "This site doesn't have any regie yet. Click on the \"New\" button in the top right of the page to add a first one."
+    )
+
+
+def test_manager_invoicing_regie_list_add_button(app, admin_user):
+    app = login(app)
+    resp = app.get(reverse('lingo-manager-invoicing-regie-list'))
+    add_button = resp.pyquery('span.actions a[href="%s"]' % reverse('lingo-manager-invoicing-regie-add'))
+    assert add_button.text() == 'New regie'
+
+
+def test_manager_invoicing_regie_list_show_objetcs(app, admin_user):
+    app = login(app)
+    regie = Regie.objects.create(label='Foo')
+    resp = app.get(reverse('lingo-manager-invoicing-regie-list'))
+    href = resp.pyquery(
+        'div#content div ul li a[href="%s"]'
+        % reverse('lingo-manager-invoicing-regie-detail', kwargs={'pk': regie.pk})
+    )
+    assert href.text() == 'Foo [identifier: foo]'
+
+
+def test_manager_invoicing_regie_add(app, admin_user):
+    app = login(app)
+    assert Regie.objects.count() == 0
+    group = Group.objects.create(name='role-foo')
+    resp = app.get(reverse('lingo-manager-invoicing-regie-add'))
+    h2 = resp.pyquery('div#appbar h2')
+    assert h2.text() == 'New regie'
+    form = resp.form
+    form.set('label', 'Foo')
+    form.set('description', 'foo description')
+    form.set('edit_role', group.id)
+    response = form.submit().follow()
+    assert Regie.objects.count() == 1
+    regie = Regie.objects.first()
+    assert regie.label == 'Foo'
+    assert regie.slug == 'foo'
+    assert regie.description == 'foo description'
+    assert regie.edit_role == group
+    assert urlparse(response.request.url).path == reverse(
+        'lingo-manager-invoicing-regie-detail', kwargs={'pk': regie.pk}
+    )
+
+
+def test_manager_invoicing_regie_detail(app, admin_user):
+    app = login(app)
+    group = Group.objects.create(name='role-foo')
+    regie = Regie.objects.create(label='Foo', description='foo description', edit_role=group)
+    resp = app.get(reverse('lingo-manager-invoicing-regie-detail', kwargs={'pk': regie.pk}))
+    h2 = resp.pyquery('div#appbar h2')
+    assert h2.text() == 'Regie - Foo'
+    descr = resp.pyquery('div#content div.bo-block')[0]
+    assert descr.text == 'foo description'
+    slug = resp.pyquery('div#content div.bo-block ul li')[0]
+    assert slug.text == 'slug\xa0: foo'
+    edit_role = resp.pyquery('div#content div.bo-block ul li')[1]
+    assert edit_role.text == 'edit role\xa0: role-foo'
+    edit_button = resp.pyquery(
+        'span.actions a[href="%s"]' % reverse('lingo-manager-invoicing-regie-edit', kwargs={'pk': regie.pk})
+    )
+    assert edit_button.text() == 'Edit'
+    delete_button = resp.pyquery(
+        'span.actions a[href="%s"]' % reverse('lingo-manager-invoicing-regie-delete', kwargs={'pk': regie.pk})
+    )
+    assert delete_button.text() == 'Delete'
+
+
+def test_manager_invoicing_regie_edit(app, admin_user):
+    app = login(app)
+    group_foo = Group.objects.create(name='role-foo')
+    group_bar = Group.objects.create(name='role-bar')
+    regie = Regie.objects.create(label='Foo', description='foo description', edit_role=group_foo)
+    resp = app.get(reverse('lingo-manager-invoicing-regie-edit', kwargs={'pk': regie.pk}))
+    h2 = resp.pyquery('div#appbar h2')
+    assert h2.text() == 'Edit regie - Foo'
+    form = resp.form
+    form.set('label', 'Foo bar')
+    form.set('description', 'foo new description')
+    form.set('edit_role', group_bar.id)
+    response = form.submit().follow()
+    assert Regie.objects.count() == 1
+    regie = Regie.objects.first()
+    assert regie.label == 'Foo bar'
+    assert regie.slug == 'foo'
+    assert regie.description == 'foo new description'
+    assert regie.edit_role == group_bar
+    assert urlparse(response.request.url).path == reverse(
+        'lingo-manager-invoicing-regie-detail', kwargs={'pk': regie.pk}
+    )
+
+
+def test_manager_invoicing_regie_delete(app, admin_user):
+    app = login(app)
+    group = Group.objects.create(name='role-foo')
+    regie = Regie.objects.create(label='Foo', description='foo description', edit_role=group)
+    assert Regie.objects.count() == 1
+    resp = app.get(reverse('lingo-manager-invoicing-regie-delete', kwargs={'pk': regie.pk}))
+    response = resp.form.submit().follow()
+    assert Regie.objects.count() == 0
+    assert urlparse(response.request.url).path == reverse('lingo-manager-invoicing-regie-list')
-- 
2.30.2

