invoicing: add a global export/import for invoicing config (#78125)
This commit is contained in:
parent
1813a9c415
commit
2b3f25985b
|
@ -23,6 +23,14 @@ from gadjo.forms.widgets import MultiSelectWidget
|
|||
from lingo.invoicing.models import Campaign, DraftInvoice, DraftInvoiceLine, Invoice, InvoiceLine, Regie
|
||||
|
||||
|
||||
class ExportForm(forms.Form):
|
||||
regies = forms.BooleanField(label=_('Regies'), required=False, initial=True)
|
||||
|
||||
|
||||
class ImportForm(forms.Form):
|
||||
config_json = forms.FileField(label=_('Export File'))
|
||||
|
||||
|
||||
class RegieForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Regie
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
{% extends "lingo/invoicing/manager_home.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
{{ block.super }}
|
||||
<a href="{% url 'lingo-manager-invoicing-config-export' %}">{% trans 'Export' %}</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block appbar %}
|
||||
<h2>{% trans "Export" %}</h2>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<div class="buttons">
|
||||
<button class="submit-button">{% trans "Export" %}</button>
|
||||
<a class="cancel" href="{% url 'lingo-manager-invoicing-home' %}">{% trans 'Cancel' %}</a>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -1,13 +1,13 @@
|
|||
{% extends "lingo/invoicing/manager_regie_list.html" %}
|
||||
{% extends "lingo/invoicing/manager_home.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
{{ block.super }}
|
||||
<a href="{% url 'lingo-manager-invoicing-regie-import' %}">{% trans 'Import' %}</a>
|
||||
<a href="{% url 'lingo-manager-invoicing-config-import' %}">{% trans 'Import' %}</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block appbar %}
|
||||
<h2>{% trans "Import Regies" %}</h2>
|
||||
<h2>{% trans "Import" %}</h2>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
@ -16,7 +16,7 @@
|
|||
{{ form.as_p }}
|
||||
<div class="buttons">
|
||||
<button class="submit-button">{% trans "Import" %}</button>
|
||||
<a class="cancel" href="{% url 'lingo-manager-invoicing-regie-list' %}">{% trans 'Cancel' %}</a>
|
||||
<a class="cancel" href="{% url 'lingo-manager-invoicing-home' %}">{% trans 'Cancel' %}</a>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -8,6 +8,13 @@
|
|||
|
||||
{% block appbar %}
|
||||
<h2>{% trans 'Invoicing' %}</h2>
|
||||
<span class="actions">
|
||||
<a class="extra-actions-menu-opener"></a>
|
||||
<ul class="extra-actions-menu">
|
||||
<li><a rel="popup" href="{% url 'lingo-manager-invoicing-config-import' %}">{% trans 'Import' %}</a></li>
|
||||
<li><a rel="popup" href="{% url 'lingo-manager-invoicing-config-export' %}" data-autoclose-dialog="true">{% trans 'Export' %}</a></li>
|
||||
</ul>
|
||||
</span>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
|
|
@ -9,10 +9,14 @@
|
|||
{% block appbar %}
|
||||
<h2>{% trans 'Regie' %} - {{ regie }}</h2>
|
||||
<span class="actions">
|
||||
{% if not has_related_objects %}
|
||||
<a href="{% url 'lingo-manager-invoicing-regie-delete' pk=regie.pk %}" rel="popup">{% trans "Delete" %}</a>
|
||||
{% endif %}
|
||||
<a href="{% url 'lingo-manager-invoicing-regie-edit' pk=regie.pk %}" rel="popup">{% trans "Edit" %}</a>
|
||||
<a class="extra-actions-menu-opener"></a>
|
||||
<ul class="extra-actions-menu">
|
||||
<li><a href="{% url 'lingo-manager-invoicing-regie-edit' pk=regie.pk %}" rel="popup">{% trans "Edit" %}</a></li>
|
||||
<li><a href="{% url 'lingo-manager-invoicing-regie-export' pk=regie.pk %}">{% trans 'Export' %}</a></li>
|
||||
{% if not has_related_objects %}
|
||||
<li><a href="{% url 'lingo-manager-invoicing-regie-delete' pk=regie.pk %}" rel="popup">{% trans "Delete" %}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
<a href="{% url 'lingo-manager-invoicing-non-invoiced-line-list' regie_pk=regie.pk %}">{% trans 'Non invoiced lines' %}</a>
|
||||
<a href="{% url 'lingo-manager-invoicing-regie-invoice-list' regie_pk=regie.pk %}">{% trans 'Invoices' %}</a>
|
||||
</span>
|
||||
|
|
|
@ -9,15 +9,6 @@
|
|||
{% block appbar %}
|
||||
<h2>{% trans 'Regies' %}</h2>
|
||||
<span class="actions">
|
||||
<a class="extra-actions-menu-opener"></a>
|
||||
<ul class="extra-actions-menu">
|
||||
<li>
|
||||
<a href="{% url 'lingo-manager-invoicing-regie-import' %}">{% trans 'Import' %}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'lingo-manager-invoicing-regie-export' %}">{% trans 'Export' %}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<a rel="popup" href="{% url 'lingo-manager-invoicing-regie-add' %}">{% trans 'New regie' %}</a>
|
||||
</span>
|
||||
{% endblock %}
|
||||
|
|
|
@ -23,6 +23,8 @@ from .views import regie as regie_views
|
|||
|
||||
urlpatterns = [
|
||||
path('', home_views.home, name='lingo-manager-invoicing-home'),
|
||||
path('import/', home_views.config_import, name='lingo-manager-invoicing-config-import'),
|
||||
path('export/', home_views.config_export, name='lingo-manager-invoicing-config-export'),
|
||||
path('regies/', regie_views.regies_list, name='lingo-manager-invoicing-regie-list'),
|
||||
path(
|
||||
'regie/add/',
|
||||
|
@ -44,8 +46,11 @@ urlpatterns = [
|
|||
regie_views.regie_delete,
|
||||
name='lingo-manager-invoicing-regie-delete',
|
||||
),
|
||||
path('regies/import/', regie_views.regies_import, name='lingo-manager-invoicing-regie-import'),
|
||||
path('regies/export/', regie_views.regies_export, name='lingo-manager-invoicing-regie-export'),
|
||||
path(
|
||||
'regie/<int:pk>/export/',
|
||||
regie_views.regie_export,
|
||||
name='lingo-manager-invoicing-regie-export',
|
||||
),
|
||||
path(
|
||||
'regie/<int:regie_pk>/campaign/add/',
|
||||
campaign_views.campaign_add,
|
||||
|
|
|
@ -17,12 +17,13 @@
|
|||
import collections
|
||||
import datetime
|
||||
|
||||
from django.db import transaction
|
||||
from django.test.client import RequestFactory
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from lingo.agendas.chrono import get_check_status, get_subscriptions
|
||||
from lingo.agendas.models import Agenda
|
||||
from lingo.invoicing.models import DraftInvoice, DraftInvoiceLine, InjectedLine
|
||||
from lingo.invoicing.models import DraftInvoice, DraftInvoiceLine, InjectedLine, Regie
|
||||
from lingo.pricing.models import AgendaPricing, AgendaPricingNotFound, PricingError
|
||||
|
||||
|
||||
|
@ -310,3 +311,40 @@ def generate_invoices_from_lines(all_lines, pool):
|
|||
invoices.append(invoice)
|
||||
|
||||
return invoices
|
||||
|
||||
|
||||
def export_site(
|
||||
regies=True,
|
||||
):
|
||||
'''Dump site objects to JSON-dumpable dictionnary'''
|
||||
data = collections.OrderedDict()
|
||||
if regies:
|
||||
data['regies'] = [x.export_json() for x in Regie.objects.all()]
|
||||
return data
|
||||
|
||||
|
||||
def import_site(data, if_empty=False, clean=False):
|
||||
if if_empty and (Regie.objects.exists()):
|
||||
return
|
||||
|
||||
if clean:
|
||||
Regie.objects.all().delete()
|
||||
|
||||
results = {
|
||||
key: collections.defaultdict(list)
|
||||
for key in [
|
||||
'regies',
|
||||
]
|
||||
}
|
||||
|
||||
with transaction.atomic():
|
||||
for cls, key in ((Regie, 'regies'),):
|
||||
objs = data.get(key, [])
|
||||
for obj in objs:
|
||||
created, obj = cls.import_json(obj)
|
||||
results[key]['all'].append(obj)
|
||||
if created:
|
||||
results[key]['created'].append(obj)
|
||||
else:
|
||||
results[key]['updated'].append(obj)
|
||||
return results
|
||||
|
|
|
@ -14,7 +14,20 @@
|
|||
# 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.views.generic import TemplateView
|
||||
import datetime
|
||||
import json
|
||||
|
||||
from django.contrib import messages
|
||||
from django.http import HttpResponse, HttpResponseRedirect
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.utils.encoding import force_str
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils.translation import ngettext
|
||||
from django.views.generic import FormView, TemplateView
|
||||
|
||||
from lingo.invoicing.forms import ExportForm, ImportForm
|
||||
from lingo.invoicing.utils import export_site, import_site
|
||||
from lingo.utils.misc import LingoImportError
|
||||
|
||||
|
||||
class HomeView(TemplateView):
|
||||
|
@ -22,3 +35,100 @@ class HomeView(TemplateView):
|
|||
|
||||
|
||||
home = HomeView.as_view()
|
||||
|
||||
|
||||
class ConfigExportView(FormView):
|
||||
form_class = ExportForm
|
||||
template_name = 'lingo/invoicing/export.html'
|
||||
|
||||
def form_valid(self, form):
|
||||
response = HttpResponse(content_type='application/json')
|
||||
today = datetime.date.today()
|
||||
response['Content-Disposition'] = 'attachment; filename="export_invoicing_config_{}.json"'.format(
|
||||
today.strftime('%Y%m%d')
|
||||
)
|
||||
json.dump(export_site(**form.cleaned_data), response, indent=2)
|
||||
return response
|
||||
|
||||
|
||||
config_export = ConfigExportView.as_view()
|
||||
|
||||
|
||||
class ConfigImportView(FormView):
|
||||
form_class = ImportForm
|
||||
template_name = 'lingo/invoicing/import.html'
|
||||
success_url = reverse_lazy('lingo-manager-invoicing-home')
|
||||
|
||||
def form_valid(self, form):
|
||||
try:
|
||||
config_json = json.loads(force_str(self.request.FILES['config_json'].read()))
|
||||
except ValueError:
|
||||
form.add_error('config_json', _('File is not in the expected JSON format.'))
|
||||
return self.form_invalid(form)
|
||||
|
||||
try:
|
||||
results = import_site(config_json)
|
||||
except LingoImportError as exc:
|
||||
form.add_error('config_json', '%s' % exc)
|
||||
return self.form_invalid(form)
|
||||
except KeyError as exc:
|
||||
form.add_error('config_json', _('Key "%s" is missing.') % exc.args[0])
|
||||
return self.form_invalid(form)
|
||||
|
||||
import_messages = {
|
||||
'regies': {
|
||||
'create_noop': _('No regie created.'),
|
||||
'create': lambda x: ngettext(
|
||||
'A regie has been created.',
|
||||
'%(count)d regies have been created.',
|
||||
x,
|
||||
),
|
||||
'update_noop': _('No regie updated.'),
|
||||
'update': lambda x: ngettext(
|
||||
'A regie has been updated.',
|
||||
'%(count)d regies have been updated.',
|
||||
x,
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
global_noop = True
|
||||
for obj_name, obj_results in results.items():
|
||||
if obj_results['all']:
|
||||
global_noop = False
|
||||
count = len(obj_results['created'])
|
||||
if not count:
|
||||
message1 = import_messages[obj_name].get('create_noop')
|
||||
else:
|
||||
message1 = import_messages[obj_name]['create'](count) % {'count': count}
|
||||
|
||||
count = len(obj_results['updated'])
|
||||
if not count:
|
||||
message2 = import_messages[obj_name]['update_noop']
|
||||
else:
|
||||
message2 = import_messages[obj_name]['update'](count) % {'count': count}
|
||||
|
||||
if message1:
|
||||
obj_results['messages'] = "%s %s" % (message1, message2)
|
||||
else:
|
||||
obj_results['messages'] = message2
|
||||
|
||||
(r_count,) = (len(results['regies']['all']),)
|
||||
if (r_count,) == (1,):
|
||||
# only one regie imported, redirect to regie page
|
||||
return HttpResponseRedirect(
|
||||
reverse(
|
||||
'lingo-manager-invoicing-regie-detail',
|
||||
kwargs={'pk': results['regies']['all'][0].pk},
|
||||
)
|
||||
)
|
||||
|
||||
if global_noop:
|
||||
messages.info(self.request, _('No data found.'))
|
||||
else:
|
||||
messages.info(self.request, results['regies']['messages'])
|
||||
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
config_import = ConfigImportView.as_view()
|
||||
|
|
|
@ -18,30 +18,17 @@ import collections
|
|||
import datetime
|
||||
import json
|
||||
|
||||
from django.contrib import messages
|
||||
from django.db import transaction
|
||||
from django.db.models import CharField, IntegerField, JSONField, Value
|
||||
from django.http import HttpResponse
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils.translation import ngettext
|
||||
from django.views.generic import CreateView, DeleteView, DetailView, FormView, ListView, UpdateView
|
||||
from django.urls import reverse
|
||||
from django.views.generic import CreateView, DeleteView, DetailView, ListView, UpdateView
|
||||
|
||||
from lingo.agendas.models import Agenda
|
||||
from lingo.invoicing.forms import RegieForm, RegieInvoiceFilterSet
|
||||
from lingo.invoicing.models import (
|
||||
Counter,
|
||||
InjectedLine,
|
||||
Invoice,
|
||||
InvoiceLine,
|
||||
InvoicePayment,
|
||||
Pool,
|
||||
Regie,
|
||||
RegieImportError,
|
||||
)
|
||||
from lingo.invoicing.models import Counter, InjectedLine, Invoice, InvoiceLine, InvoicePayment, Pool, Regie
|
||||
from lingo.invoicing.views.utils import PDFMixin
|
||||
from lingo.pricing.forms import ImportForm
|
||||
|
||||
|
||||
def import_regies(data):
|
||||
|
@ -128,66 +115,21 @@ class RegieDeleteView(DeleteView):
|
|||
regie_delete = RegieDeleteView.as_view()
|
||||
|
||||
|
||||
class RegiesExportView(ListView):
|
||||
class RegieExport(DetailView):
|
||||
model = Regie
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
response = HttpResponse(content_type='application/json')
|
||||
today = datetime.date.today()
|
||||
attachment = 'attachment; filename="export_regies_{}.json"'.format(today.strftime('%Y%m%d'))
|
||||
attachment = 'attachment; filename="export_regie_{}_{}.json"'.format(
|
||||
self.get_object().slug, today.strftime('%Y%m%d')
|
||||
)
|
||||
response['Content-Disposition'] = attachment
|
||||
json.dump({'regies': [regie.export_json() for regie in self.get_queryset()]}, response, indent=2)
|
||||
json.dump({'regies': [self.get_object().export_json()]}, response, indent=2)
|
||||
return response
|
||||
|
||||
|
||||
regies_export = RegiesExportView.as_view()
|
||||
|
||||
|
||||
class RegiesImportView(FormView):
|
||||
form_class = ImportForm
|
||||
template_name = 'lingo/invoicing/manager_import.html'
|
||||
success_url = reverse_lazy('lingo-manager-invoicing-regie-list')
|
||||
|
||||
def form_valid(self, form):
|
||||
try:
|
||||
config_json = json.loads(self.request.FILES['config_json'].read())
|
||||
except ValueError:
|
||||
form.add_error('config_json', _('File is not in the expected JSON format.'))
|
||||
return self.form_invalid(form)
|
||||
|
||||
try:
|
||||
results = import_regies(config_json)
|
||||
except RegieImportError as exc:
|
||||
form.add_error('config_json', '%s' % exc)
|
||||
return self.form_invalid(form)
|
||||
|
||||
import_messages = {
|
||||
'create': lambda x: ngettext(
|
||||
'A regie was created.',
|
||||
'%(count)d regies were created.',
|
||||
x,
|
||||
),
|
||||
'update': lambda x: ngettext(
|
||||
'A regie was updated.',
|
||||
'%(count)d regie were updated.',
|
||||
x,
|
||||
),
|
||||
}
|
||||
create_message = _('No regie created.')
|
||||
update_message = _('No regie updated.')
|
||||
created = len(results.get('created', []))
|
||||
updated = len(results.get('updated', []))
|
||||
if created:
|
||||
create_message = import_messages.get('create')(created) % {'count': created}
|
||||
if updated:
|
||||
update_message = import_messages.get('update')(updated) % {'count': updated}
|
||||
message = "%s %s" % (create_message, update_message)
|
||||
messages.info(self.request, message)
|
||||
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
regies_import = RegiesImportView.as_view()
|
||||
regie_export = RegieExport.as_view()
|
||||
|
||||
|
||||
class NonInvoicedLineListView(ListView):
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "lingo/pricing/manager_pricing_list.html" %}
|
||||
{% extends "lingo/pricing/manager_home.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
|
@ -16,7 +16,7 @@
|
|||
{{ form.as_p }}
|
||||
<div class="buttons">
|
||||
<button class="submit-button">{% trans "Export" %}</button>
|
||||
<a class="cancel" href="{% url 'lingo-manager-pricing-list' %}">{% trans 'Cancel' %}</a>
|
||||
<a class="cancel" href="{% url 'lingo-manager-pricing-home' %}">{% trans 'Cancel' %}</a>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "lingo/pricing/manager_pricing_list.html" %}
|
||||
{% extends "lingo/pricing/manager_home.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
|
@ -16,7 +16,7 @@
|
|||
{{ form.as_p }}
|
||||
<div class="buttons">
|
||||
<button class="submit-button">{% trans "Import" %}</button>
|
||||
<a class="cancel" href="{% url 'lingo-manager-pricing-list' %}">{% trans 'Cancel' %}</a>
|
||||
<a class="cancel" href="{% url 'lingo-manager-pricing-home' %}">{% trans 'Cancel' %}</a>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
import copy
|
||||
import json
|
||||
|
||||
import pytest
|
||||
from webtest import Upload
|
||||
|
||||
from lingo.invoicing.models import Regie
|
||||
from tests.utils import login
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
|
||||
def test_export_site(freezer, app, admin_user):
|
||||
freezer.move_to('2020-06-15')
|
||||
login(app)
|
||||
resp = app.get('/manage/invoicing/')
|
||||
resp = resp.click('Export')
|
||||
|
||||
resp = resp.form.submit()
|
||||
assert resp.headers['content-type'] == 'application/json'
|
||||
assert (
|
||||
resp.headers['content-disposition'] == 'attachment; filename="export_invoicing_config_20200615.json"'
|
||||
)
|
||||
|
||||
site_json = json.loads(resp.text)
|
||||
assert site_json == {
|
||||
'regies': [],
|
||||
}
|
||||
|
||||
Regie.objects.create(label='Foo Bar')
|
||||
resp = app.get('/manage/invoicing/export/')
|
||||
resp = resp.form.submit()
|
||||
|
||||
site_json = json.loads(resp.text)
|
||||
assert len(site_json['regies']) == 1
|
||||
|
||||
|
||||
@pytest.mark.freeze_time('2023-06-02')
|
||||
def test_import_regie(app, admin_user):
|
||||
regie = Regie.objects.create(label='Foo bar')
|
||||
|
||||
app = login(app)
|
||||
resp = app.get('/manage/invoicing/regie/%s/' % regie.pk)
|
||||
resp = resp.click(href='/manage/invoicing/regie/%s/export/' % regie.pk)
|
||||
assert resp.headers['content-type'] == 'application/json'
|
||||
assert resp.headers['content-disposition'] == 'attachment; filename="export_regie_foo-bar_20230602.json"'
|
||||
regie_export = resp.text
|
||||
|
||||
# existing regie
|
||||
resp = app.get('/manage/invoicing/', status=200)
|
||||
resp = resp.click('Import')
|
||||
resp.form['config_json'] = Upload('export.json', regie_export.encode('utf-8'), 'application/json')
|
||||
resp = resp.form.submit()
|
||||
assert resp.location.endswith('/manage/invoicing/regie/%s/' % regie.pk)
|
||||
resp = resp.follow()
|
||||
assert 'No regie created. A regie has been updated.' not in resp.text
|
||||
assert Regie.objects.count() == 1
|
||||
|
||||
# new regie
|
||||
Regie.objects.all().delete()
|
||||
resp = app.get('/manage/invoicing/', status=200)
|
||||
resp = resp.click('Import')
|
||||
resp.form['config_json'] = Upload('export.json', regie_export.encode('utf-8'), 'application/json')
|
||||
resp = resp.form.submit()
|
||||
regie = Regie.objects.latest('pk')
|
||||
assert resp.location.endswith('/manage/invoicing/regie/%s/' % regie.pk)
|
||||
resp = resp.follow()
|
||||
assert 'A regie has been created. No regie updated.' not in resp.text
|
||||
assert Regie.objects.count() == 1
|
||||
|
||||
# multiple regies
|
||||
regies = json.loads(regie_export)
|
||||
regies['regies'].append(copy.copy(regies['regies'][0]))
|
||||
regies['regies'].append(copy.copy(regies['regies'][0]))
|
||||
regies['regies'][1]['label'] = 'Foo bar 2'
|
||||
regies['regies'][1]['slug'] = 'foo-bar-2'
|
||||
regies['regies'][2]['label'] = 'Foo bar 3'
|
||||
regies['regies'][2]['slug'] = 'foo-bar-3'
|
||||
|
||||
resp = app.get('/manage/invoicing/', status=200)
|
||||
resp = resp.click('Import')
|
||||
resp.form['config_json'] = Upload('export.json', json.dumps(regies).encode('utf-8'), 'application/json')
|
||||
resp = resp.form.submit()
|
||||
assert resp.location.endswith('/manage/invoicing/')
|
||||
resp = resp.follow()
|
||||
assert '2 regies have been created. A regie has been updated.' in resp.text
|
||||
assert Regie.objects.count() == 3
|
||||
|
||||
Regie.objects.all().delete()
|
||||
resp = app.get('/manage/invoicing/', status=200)
|
||||
resp = resp.click('Import')
|
||||
resp.form['config_json'] = Upload('export.json', json.dumps(regies).encode('utf-8'), 'application/json')
|
||||
resp = resp.form.submit().follow()
|
||||
assert '3 regies have been created. No regie updated.' in resp.text
|
||||
assert Regie.objects.count() == 3
|
|
@ -1,5 +1,4 @@
|
|||
import datetime
|
||||
import json
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import pytest
|
||||
|
@ -7,7 +6,6 @@ from django.contrib.auth.models import Group
|
|||
from django.urls import reverse
|
||||
from django.utils.formats import date_format
|
||||
from django.utils.timezone import localtime
|
||||
from webtest import Upload
|
||||
|
||||
from lingo.agendas.models import Agenda
|
||||
from lingo.invoicing.models import (
|
||||
|
@ -225,29 +223,6 @@ def test_manager_invoicing_regie_delete(app, admin_user):
|
|||
assert Counter.objects.count() == 0
|
||||
|
||||
|
||||
def test_manager_invoicing_regie_import_export(app, admin_user, freezer):
|
||||
freezer.move_to('2020-06-15')
|
||||
app = login(app)
|
||||
group = Group.objects.create(name='role-foo')
|
||||
regie1 = Regie.objects.create(label='Foo', description='foo description', cashier_role=group)
|
||||
Regie.objects.create(label='Bar', description='bar description', cashier_role=group)
|
||||
response = app.get(reverse('lingo-manager-invoicing-regie-export'))
|
||||
assert response.headers['content-type'] == 'application/json'
|
||||
assert response.headers['content-disposition'] == 'attachment; filename="export_regies_20200615.json"'
|
||||
regies_export = response.text
|
||||
regies_json = json.loads(regies_export)
|
||||
assert len(regies_json['regies']) == 2
|
||||
|
||||
regie1.delete()
|
||||
assert Regie.objects.count() == 1
|
||||
response = app.get(reverse('lingo-manager-invoicing-regie-import'))
|
||||
response.form['config_json'] = Upload('export.json', regies_export.encode('utf-8'), 'application/json')
|
||||
response = response.form.submit().follow()
|
||||
assert urlparse(response.request.url).path == reverse('lingo-manager-invoicing-regie-list')
|
||||
assert 'A regie was created. A regie was updated.' in response.text
|
||||
assert Regie.objects.count() == 2
|
||||
|
||||
|
||||
def test_non_invoiced_line_list(app, admin_user):
|
||||
regie = Regie.objects.create(label='Regie')
|
||||
other_regie = Regie.objects.create(label='Other Regie')
|
||||
|
|
Loading…
Reference in New Issue