Banktransfer: Do not allow concurrent import jobs

This commit is contained in:
Raphael Michel
2016-09-21 23:03:55 +02:00
parent 0e4a232d5d
commit f27f98c769
4 changed files with 50 additions and 25 deletions

View File

@@ -112,14 +112,14 @@ var bankimport_transactionlist = {
} }
if ($("[data-job-waiting]").length) { if ($("[data-job-waiting]").length) {
window.setInterval(bankimport_transactionlist.check_state, 750); window.setTimeout(bankimport_transactionlist.check_state, 750);
} }
}, },
check_state: function () { check_state: function () {
$.getJSON(location.pathname + '?ajax=1', function (data) { $.getJSON($("[data-job-waiting-url]").attr("data-job-waiting-url"), function (data) {
if (data.state == 'running' || data.state == 'pending') { if (data.state == 'running' || data.state == 'pending') {
window.setInterval(check_state, 750); window.setTimeout(bankimport_transactionlist.check_state, 750);
} else { } else {
location.reload(); location.reload();
} }

View File

@@ -13,16 +13,23 @@
<p>{% blocktrans trimmed %} <p>{% blocktrans trimmed %}
Currently, this feature supports <code>.csv</code> files and files in the MT940 format. Currently, this feature supports <code>.csv</code> files and files in the MT940 format.
{% endblocktrans %}</p> {% endblocktrans %}</p>
<form action="" method="post" enctype="multipart/form-data" class="form-inline"> {% if job_running %}
{% csrf_token %} <div class="alert alert-info" data-job-waiting data-job-waiting-url="{% url "plugins:banktransfer:import.job" event=request.event.slug organizer=request.event.organizer.slug job=job_running.pk %}?ajax=1">
<div class="form-group"> <span class="fa fa-cog fa-spin"></span>
<label for="file">{% trans "Import file" %}: </label> <input id="file" type="file" name="file"/> {% trans "An import is currently being processed, please try again in a few minutes." %}
</div> </div>
<div class="clearfix"></div> {% else %}
<button class="btn btn-primary pull-right" type="submit"> <form action="" method="post" enctype="multipart/form-data" class="form-inline">
<span class="icon icon-upload"></span> {% trans "Start upload" %} {% csrf_token %}
</button> <div class="form-group">
</form> <label for="file">{% trans "Import file" %}: </label> <input id="file" type="file" name="file"/>
</div>
<div class="clearfix"></div>
<button class="btn btn-primary pull-right" type="submit">
<span class="icon icon-upload"></span> {% trans "Start upload" %}
</button>
</form>
{% endif %}
</div> </div>
</div> </div>
{% if transactions_unhandled|length > 0 %} {% if transactions_unhandled|length > 0 %}
@@ -32,19 +39,20 @@
</div> </div>
<div class="panel-body"> <div class="panel-body">
<p> <p>
<form class="form-inline helper-display-inline" action="" method="get"> <form class="form-inline helper-display-inline" action="" method="get">
<input type="text" name="search" class="form-control" placeholder="{% trans "Search" %}" value="{{ request.GET.search }}"> <input type="text" name="search" class="form-control" placeholder="{% trans "Search" %}"
value="{{ request.GET.search }}">
</form>
<button class="btn btn-primary" type="submit">{% trans "Filter" %}</button>
{% if not request.GET.search %}
<form action="" method="post" class="helper-display-inline pull-right">
{% csrf_token %}
<button class="btn btn-danger" type="submit" name="discard" value="all">
<span class="fa fa-trash"></span>
{% trans "Discard all" %}
</button>
</form> </form>
<button class="btn btn-primary" type="submit">{% trans "Filter" %}</button> {% endif %}
{% if not request.GET.search %}
<form action="" method="post" class="helper-display-inline pull-right">
{% csrf_token %}
<button class="btn btn-danger" type="submit" name="discard" value="all">
<span class="fa fa-trash"></span>
{% trans "Discard all" %}
</button>
</form>
{% endif %}
</p> </p>
{% include "pretixcontrol/pagination.html" %} {% include "pretixcontrol/pagination.html" %}

View File

@@ -3,7 +3,7 @@
{% block inner %} {% block inner %}
<h2>{% trans "Import result" %}</h2> <h2>{% trans "Import result" %}</h2>
{% if job.state == "running" or job.state == "pending" %} {% if job.state == "running" or job.state == "pending" %}
<div class="empty-collection" data-job-waiting> <div class="empty-collection" data-job-waiting data-job-waiting-url="{% url "plugins:banktransfer:import.job" event=request.event.slug organizer=request.event.organizer.slug job=job.pk %}?ajax=1">
<p> <p>
<span class="fa big-grey-icon fa-cog fa big-rotating-icon"></span> <span class="fa big-grey-icon fa-cog fa big-rotating-icon"></span>
</p> </p>

View File

@@ -1,6 +1,7 @@
import csv import csv
import json import json
import logging import logging
from datetime import timedelta
from locale import format as lformat from locale import format as lformat
from django.contrib import messages from django.contrib import messages
@@ -9,6 +10,7 @@ from django.db.models import Q
from django.http import JsonResponse from django.http import JsonResponse
from django.shortcuts import get_object_or_404, redirect, render from django.shortcuts import get_object_or_404, redirect, render
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.timezone import now
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.views.generic import DetailView, ListView, TemplateView, View from django.views.generic import DetailView, ListView, TemplateView, View
@@ -303,6 +305,13 @@ class ImportView(EventPermissionRequiredMixin, ListView):
'rows': parsed 'rows': parsed
}) })
@cached_property
def job_running(self):
return BankImportJob.objects.filter(
event=self.request.event, state=BankImportJob.STATE_RUNNING,
created__lte=now() - timedelta(minutes=30) # safety timeout
).first()
def redirect_back(self): def redirect_back(self):
return redirect(reverse('plugins:banktransfer:import', kwargs={ return redirect(reverse('plugins:banktransfer:import', kwargs={
'event': self.request.event.slug, 'event': self.request.event.slug,
@@ -310,6 +319,9 @@ class ImportView(EventPermissionRequiredMixin, ListView):
})) }))
def start_processing(self, parsed): def start_processing(self, parsed):
if self.job_running:
messages.error(self.request, _('An import is currently being processed, please try again in a few minutes.'))
return self.redirect_back()
job = BankImportJob.objects.create(event=self.request.event) job = BankImportJob.objects.create(event=self.request.event)
process_banktransfers.apply_async(kwargs={ process_banktransfers.apply_async(kwargs={
'event': self.request.event.pk, 'event': self.request.event.pk,
@@ -321,3 +333,8 @@ class ImportView(EventPermissionRequiredMixin, ListView):
'organizer': self.request.event.organizer.slug, 'organizer': self.request.event.organizer.slug,
'job': job.pk 'job': job.pk
})) }))
def get_context_data(self, **kwargs):
ctx = super().get_context_data()
ctx['job_running'] = self.job_running
return ctx