From de62241dc7f582e99ec6b0a428aa4774c9689e2c Mon Sep 17 00:00:00 2001
From: Emanuel Schuetze
Date: Wed, 9 Nov 2011 22:53:10 +0100
Subject: [PATCH] Application: Added import (#55) and trivial changes (#56)
function. Thanks to Rene Koecher!
---
openslides/application/forms.py | 10 +-
openslides/application/models.py | 10 +-
.../application/base_application.html | 1 +
.../templates/application/import.html | 21 ++
openslides/application/urls.py | 3 +
openslides/application/views.py | 112 +++++-
openslides/locale/de/LC_MESSAGES/django.po | 347 +++++++++++-------
7 files changed, 369 insertions(+), 135 deletions(-)
create mode 100644 openslides/application/templates/application/import.html
diff --git a/openslides/application/forms.py b/openslides/application/forms.py
index 5ff9421a4..164c8564c 100644
--- a/openslides/application/forms.py
+++ b/openslides/application/forms.py
@@ -10,7 +10,7 @@
:license: GNU GPL, see LICENSE for more details.
"""
-from django.forms import ModelForm, Form, CharField, Textarea, TextInput, ModelMultipleChoiceField, ModelChoiceField
+from django.forms import ModelForm, Form, CharField, Textarea, TextInput, ModelMultipleChoiceField, ModelChoiceField, BooleanField, FileField, FileInput
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
@@ -41,7 +41,7 @@ class ApplicationForm(Form):
title = CharField(widget=TextInput(), label=_("Title"))
text = CharField(widget=Textarea(), label=_("Text"))
reason = CharField(widget=Textarea(), required=False, label=_("Reason"))
-
+ trivial_change = BooleanField(required=False, label=_("Trivial change"), help_text=_("Trivial changes don't create a new version."))
class ApplicationManagerForm(ModelForm):
error_css_class = 'error'
@@ -54,3 +54,9 @@ class ApplicationManagerForm(ModelForm):
class Meta:
model = Application
exclude = ('number', 'status', 'permitted', 'log')
+
+class ApplicationImportForm(Form):
+ error_css_class = 'error'
+ required_css_class = 'required'
+
+ csvfile = FileField(widget=FileInput(attrs={'size':'50'}), label=_("CSV File"))
diff --git a/openslides/application/models.py b/openslides/application/models.py
index 3185130d6..5894fe542 100644
--- a/openslides/application/models.py
+++ b/openslides/application/models.py
@@ -159,7 +159,7 @@ class Application(models.Model):
else:
return 0
- def save(self, user=None, nonewversion=False):
+ def save(self, user=None, nonewversion=False, trivial_change=False):
"""
Save the Application, and create a new AVersion if necessary
"""
@@ -173,6 +173,14 @@ class Application(models.Model):
and last_version.reason == self.reason):
return # No changes
try:
+ if trivial_change and last_version is not None:
+ last_version.text = self.text
+ last_version.title = self.title
+ last_version.reason = self.reason
+ last_version.save()
+ self.writelog(_("Version %s modified") % last_version.aid, user)
+ return # Done
+
if self.title != "":
version = AVersion(title=getattr(self, 'title', ''),
text=getattr(self, 'text', ''),
diff --git a/openslides/application/templates/application/base_application.html b/openslides/application/templates/application/base_application.html
index dcf89242b..cb3d2d757 100644
--- a/openslides/application/templates/application/base_application.html
+++ b/openslides/application/templates/application/base_application.html
@@ -8,6 +8,7 @@
{%trans "All applications" %}
{% if perms.application.can_create_application or perms.application.can_manage_application %}
{%trans "New application" %}
+ {%trans 'Import applications' %}
{% endif %}
{%trans 'Print all applications' %}
diff --git a/openslides/application/templates/application/import.html b/openslides/application/templates/application/import.html
new file mode 100644
index 000000000..cc06ec413
--- /dev/null
+++ b/openslides/application/templates/application/import.html
@@ -0,0 +1,21 @@
+{% extends "application/base_application.html" %}
+{% block title %}{{ block.super }} - {%trans "Import applications" %} {% endblock %}
+
+{% block content %}
+ Import
+ {% trans 'Select a CSV file to import applications!' %}
+
+ {% trans '(Required comma separated values: number, title, text, reason, first_name, last_name
- number
and reason
are optional and may be empty)' %}
+
+
+{% endblock %}
diff --git a/openslides/application/urls.py b/openslides/application/urls.py
index 1ae07105a..d87e8474f 100644
--- a/openslides/application/urls.py
+++ b/openslides/application/urls.py
@@ -25,6 +25,9 @@ urlpatterns = patterns('application.views',
url(r'^application/new$', 'edit', \
name='application_new'),
+ url(r'^application/import$', 'application_import', \
+ name='application_import'),
+
url(r'^application/(?P\d+)/edit$', 'edit', \
name='application_edit'),
diff --git a/openslides/application/views.py b/openslides/application/views.py
index 32499c316..1435967cf 100644
--- a/openslides/application/views.py
+++ b/openslides/application/views.py
@@ -10,16 +10,22 @@
:license: GNU GPL, see LICENSE for more details.
"""
+import csv
+
from django.shortcuts import redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required
+from django.contrib.auth.models import User, Group
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext as _
+from django.utils.translation import ungettext
+from django.db import transaction
from openslides.agenda.models import Item
from openslides.application.models import Application, AVersion
from openslides.application.forms import ApplicationForm, \
- ApplicationManagerForm
+ ApplicationManagerForm, \
+ ApplicationImportForm
from openslides.participant.models import Profile
from openslides.poll.models import Poll
from openslides.poll.forms import OptionResultForm, PollForm
@@ -28,6 +34,7 @@ from openslides.utils.utils import template, permission_required, \
from openslides.utils.pdf import print_application, print_application_poll
from openslides.system.api import config_get
+from openslides.participant.api import gen_username
@permission_required('application.can_see_application')
@template('application/overview.html')
@@ -135,7 +142,7 @@ def edit(request, application_id=None):
application.title = dataform.cleaned_data['title']
application.text = dataform.cleaned_data['text']
application.reason = dataform.cleaned_data['reason']
- application.save(request.user)
+ application.save(request.user, trivial_change=dataform.cleaned_data['trivial_change'])
if is_manager:
# log added supporters
supporters_added = []
@@ -425,3 +432,104 @@ def reject_version(request, aversion_id):
gen_confirm_form(request, _('Do you really want to reject version %s?') % aversion.aid, reverse('application_version_reject', args=[aversion.id]))
return redirect(reverse('application_view', args=[application.id]))
+@permission_required('application.can_manage_applications')
+@template('application/import.html')
+def application_import(request):
+ try:
+ request.user.profile
+ messages.error(request, _('The import function is available for the superuser (without user profile) only.'))
+ return redirect(reverse('application_overview'))
+ except Profile.DoesNotExist:
+ pass
+
+ if request.method == 'POST':
+ form = ApplicationImportForm(request.POST, request.FILES)
+ if form.is_valid():
+ try:
+ users_generated = 0
+ applications_generated = 0
+ applications_modified = 0
+ with transaction.commit_on_success():
+ for (lno, line) in enumerate(csv.reader(request.FILES['csvfile'])):
+ # basic input verification
+ if lno < 1:
+ continue
+ try:
+ (number, title, text, reason, first_name, last_name) = line[:6]
+ except ValueError:
+ messages.error(request, _('Ignoring malformed line %d in import file.') % (lno + 1))
+ continue
+ form = ApplicationForm({ 'title':title, 'text':text, 'reason':reason })
+ if not form.is_valid():
+ messages.error(request, _('Ignoring malformed line %d in import file.') % (lno + 1))
+ continue
+ if number:
+ try:
+ number = abs(long(number))
+ if number < 1:
+ messages.error(request, _('Ignoring malformed line %d in import file.') % (lno + 1))
+ continue
+ except ValueError:
+ messages.error(request, _('Ignoring malformed line %d in import file.') % (lno + 1))
+ continue
+ # fetch existing users or create new users as needed
+ try:
+ user = User.objects.get(first_name=first_name, last_name=last_name)
+ except User.DoesNotExist:
+ user = None
+ if user is None:
+ user = User()
+ user.last_name = last_name
+ user.first_name = first_name
+ user.username = gen_username(first_name, last_name)
+ user.save()
+ profile = Profile()
+ profile.user = user
+ profile.group = ''
+ profile.committee = ''
+ profile.gender = 'none'
+ profile.type = 'guest'
+ profile.save()
+ users_generated += 1
+ # create / modify the application
+ application = None
+ if number:
+ try:
+ application = Application.objects.get(number=number)
+ applications_modified += 1
+ except Application.DoesNotExist:
+ application = None
+ if application is None:
+ application = Application(submitter=user)
+ if number:
+ application.number = number
+ applications_generated += 1
+
+ application.title = form.cleaned_data['title']
+ application.text = form.cleaned_data['text']
+ application.reason = form.cleaned_data['reason']
+ application.save(user, trivial_change=True)
+
+ if applications_generated:
+ messages.success(request, ungettext('%d application was successfully imported.',
+ '%d applications were successfully imported.', applications_generated) % applications_generated)
+ if applications_modified:
+ messages.success(request, ungettext('%d application was successfully modified.',
+ '%d applications were successfully modified.', applications_modified) % applications_modified)
+ if users_generated:
+ messages.success(request, ungettext('%d new user was added.', '%d new users were added.', users_generated) % users_generated)
+ return redirect(reverse('application_overview'))
+
+ except csv.Error:
+ message.error(request, _('Import aborted because of severe errors in the input file.'))
+ else:
+ messages.error(request, _('Please check the form for errors.'))
+ else:
+ messages.warning(request, _("Attention: Existing applications will be modified if you import new applications with the same number."))
+ messages.warning(request, _("Attention: Importing an application without a number multiple times will create duplicates."))
+ form = ApplicationImportForm()
+ return {
+ 'form': form,
+ }
+
+
diff --git a/openslides/locale/de/LC_MESSAGES/django.po b/openslides/locale/de/LC_MESSAGES/django.po
index 45a90bf4f..c29a845c5 100644
--- a/openslides/locale/de/LC_MESSAGES/django.po
+++ b/openslides/locale/de/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2011-11-01 08:21+0100\n"
+"POT-Creation-Date: 2011-11-09 20:57+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -32,8 +32,8 @@ msgstr "Englisch"
#: application/templates/application/poll_view.html:28
#: application/templates/application/view.html:74
#: assignment/templates/assignment/poll_view.html:16
-#: assignment/templates/assignment/view.html:179
-#: assignment/templates/assignment/view.html:183 poll/forms.py:45
+#: assignment/templates/assignment/view.html:186
+#: assignment/templates/assignment/view.html:190 poll/forms.py:45
#: utils/pdf.py:403 utils/pdf.py:483 utils/pdf.py:703 utils/utils.py:35
msgid "Yes"
msgstr "Ja"
@@ -48,7 +48,7 @@ msgstr "Ja, mit allen Kindelementen."
#: application/templates/application/poll_view.html:32
#: application/templates/application/view.html:75
#: assignment/templates/assignment/poll_view.html:17
-#: assignment/templates/assignment/view.html:180 poll/forms.py:46
+#: assignment/templates/assignment/view.html:187 poll/forms.py:46
#: utils/pdf.py:403 utils/pdf.py:484 utils/pdf.py:703 utils/utils.py:35
msgid "No"
msgstr "Nein"
@@ -64,7 +64,7 @@ msgid "Parent item"
msgstr "Elternelement"
#: agenda/models.py:35 application/forms.py:41
-#: application/templates/application/view.html:246
+#: application/templates/application/view.html:253
msgid "Title"
msgstr "Titel"
@@ -86,7 +86,7 @@ msgid "No Form for itemtype %s"
msgstr "Kein Formular für Eintrag %s"
#: agenda/models.py:189 application/forms.py:42
-#: application/templates/application/view.html:247 poll/models.py:136
+#: application/templates/application/view.html:254 poll/models.py:136
msgid "Text"
msgstr "Text"
@@ -94,7 +94,7 @@ msgstr "Text"
#: agenda/templates/agenda/overview.html:209
#: application/templates/application/edit.html:2
#: application/templates/application/view.html:2
-#: application/templates/application/view.html:213 poll/models.py:23
+#: application/templates/application/view.html:220 poll/models.py:23
#: poll/models.py:138 system/templates/system/general.html:13 utils/pdf.py:458
#: utils/pdf.py:470
msgid "Application"
@@ -144,9 +144,9 @@ msgstr "Eintrag wurde erfolgreich geändert."
msgid "Agenda item modified"
msgstr "Tagesordnungseintrag geändert"
-#: agenda/views.py:256 participant/views.py:141 participant/views.py:227
-#: participant/views.py:256 participant/views.py:313 system/views.py:32
-#: system/views.py:71
+#: agenda/views.py:256 application/views.py:532 participant/views.py:141
+#: participant/views.py:227 participant/views.py:256 participant/views.py:313
+#: system/views.py:32 system/views.py:71
msgid "Please check the form for errors."
msgstr "Bitte kontrollieren Sie das Formular nach Fehlern."
@@ -218,7 +218,7 @@ msgstr "Speichern"
#: application/templates/application/poll_view.html:53
#: assignment/templates/assignment/edit.html:18
#: assignment/templates/assignment/poll_view.html:59
-#: assignment/templates/assignment/view.html:104
+#: assignment/templates/assignment/view.html:111
#: participant/templates/participant/edit.html:21
#: participant/templates/participant/group_edit.html:17
msgid "Apply"
@@ -226,6 +226,7 @@ msgstr "Übernehmen"
#: agenda/templates/agenda/edit.html:34
#: application/templates/application/edit.html:24
+#: application/templates/application/import.html:16
#: application/templates/application/poll_view.html:57
#: assignment/templates/assignment/edit.html:22
#: assignment/templates/assignment/poll_view.html:63
@@ -331,7 +332,7 @@ msgid "Status"
msgstr "Status"
#: agenda/templates/beamer/ItemApplication.html:19 application/forms.py:51
-#: application/models.py:45 application/templates/application/overview.html:35
+#: application/models.py:46 application/templates/application/overview.html:35
#: application/templates/application/view.html:9 utils/pdf.py:350
msgid "Submitter"
msgstr "Antragsteller/in"
@@ -352,7 +353,7 @@ msgstr "Abstimmung"
#: agenda/templates/beamer/ItemAssignment.html:69
#: application/templates/application/view.html:76
#: assignment/templates/assignment/poll_view.html:18
-#: assignment/templates/assignment/view.html:181 poll/forms.py:35
+#: assignment/templates/assignment/view.html:188 poll/forms.py:35
#: poll/forms.py:47 utils/pdf.py:403 utils/pdf.py:485 utils/pdf.py:703
msgid "Abstention"
msgstr "Enthaltung"
@@ -360,7 +361,7 @@ msgstr "Enthaltung"
#: agenda/templates/beamer/ItemApplication.html:33
#: agenda/templates/beamer/ItemAssignment.html:88
#: application/templates/application/view.html:77
-#: assignment/templates/assignment/view.html:198 poll/forms.py:24
+#: assignment/templates/assignment/view.html:205 poll/forms.py:24
#: utils/pdf.py:403
msgid "Invalid"
msgstr "Ungültig"
@@ -371,8 +372,8 @@ msgstr "Ungültig"
#: application/templates/application/poll_view.html:44
#: application/templates/application/view.html:79
#: assignment/templates/assignment/poll_view.html:40
-#: assignment/templates/assignment/view.html:206
-#: assignment/templates/assignment/view.html:209 poll/forms.py:23
+#: assignment/templates/assignment/view.html:213
+#: assignment/templates/assignment/view.html:216 poll/forms.py:23
#: poll/models.py:26 utils/pdf.py:403 utils/pdf.py:602
msgid "Votes cast"
msgstr "Abgegebene Stimmen"
@@ -384,14 +385,14 @@ msgstr "Keine Abstimmungen vorhanden."
#: agenda/templates/beamer/ItemApplication.html:50
#: application/templates/application/poll_view.html:8
#: application/templates/application/poll_view.html:16
-#: application/templates/application/view.html:211 utils/pdf.py:342
+#: application/templates/application/view.html:218 utils/pdf.py:342
#: utils/pdf.py:344 utils/pdf.py:445 utils/pdf.py:447 utils/pdf.py:479
msgid "Application No."
msgstr "Antrag Nr."
#: agenda/templates/beamer/ItemApplication.html:56 application/forms.py:43
-#: application/templates/application/view.html:229
-#: application/templates/application/view.html:249 utils/pdf.py:421
+#: application/templates/application/view.html:236
+#: application/templates/application/view.html:256 utils/pdf.py:421
msgid "Reason"
msgstr "Begründung"
@@ -403,43 +404,43 @@ msgstr "Anzahl der zur Wahl stehenden Posten"
#: agenda/templates/beamer/ItemAssignment.html:30
#: agenda/templates/beamer/ItemAssignment.html:48
#: assignment/templates/assignment/overview.html:22
-#: assignment/templates/assignment/view.html:55
-#: assignment/templates/assignment/view.html:126 utils/pdf.py:543
+#: assignment/templates/assignment/view.html:62
+#: assignment/templates/assignment/view.html:133 utils/pdf.py:543
#: utils/pdf.py:563
msgid "Candidates"
msgstr "Kandidaten/innen"
#: agenda/templates/beamer/ItemAssignment.html:36
-#: assignment/templates/assignment/view.html:66
+#: assignment/templates/assignment/view.html:73
msgid "No candidates available."
msgstr "Keine Kandidaten/innen vorhanden."
#: agenda/templates/beamer/ItemAssignment.html:45
-#: assignment/templates/assignment/view.html:114
+#: assignment/templates/assignment/view.html:121
msgid "Election results"
msgstr "Wahlergebnisse"
#: agenda/templates/beamer/ItemAssignment.html:51
#: assignment/templates/assignment/poll_view.html:6
-#: assignment/templates/assignment/view.html:122
-#: assignment/templates/assignment/view.html:130 utils/pdf.py:687
+#: assignment/templates/assignment/view.html:129
+#: assignment/templates/assignment/view.html:137 utils/pdf.py:687
msgid "ballot"
msgstr "Wahlgang"
#: agenda/templates/beamer/ItemAssignment.html:60
-#: assignment/templates/assignment/view.html:166
+#: assignment/templates/assignment/view.html:173
msgid "Candidate is elected"
msgstr "Kandidat/in ist gewählt"
#: agenda/templates/beamer/ItemAssignment.html:81
-#: assignment/templates/assignment/view.html:220
+#: assignment/templates/assignment/view.html:227
msgid "No ballots available."
msgstr "Keine Wahlgänge vorhanden."
#: agenda/templates/beamer/ItemAssignment.html:85
#: application/templates/application/poll_view.html:40
#: assignment/templates/assignment/poll_view.html:36
-#: assignment/templates/assignment/view.html:195 utils/pdf.py:594
+#: assignment/templates/assignment/view.html:202 utils/pdf.py:594
msgid "Invalid votes"
msgstr "Ungültige Stimmen"
@@ -447,11 +448,23 @@ msgstr "Ungültige Stimmen"
msgid "Poll about"
msgstr "Abstimmung über"
-#: application/forms.py:52 application/models.py:47
+#: application/forms.py:44
+msgid "Trivial change"
+msgstr "Triviale Änderung"
+
+#: application/forms.py:44
+msgid "Trivial changes don't create a new version."
+msgstr "Triviale Änderungen erzeugen keine neue Version."
+
+#: application/forms.py:52 application/models.py:48
#: application/templates/application/view.html:23 utils/pdf.py:363
msgid "Supporters"
msgstr "Unterstützer/innen"
+#: application/forms.py:62 participant/forms.py:72
+msgid "CSV File"
+msgstr "CSV-Datei"
+
#: application/models.py:26
msgid "Published"
msgstr "Veröffentlicht"
@@ -461,12 +474,12 @@ msgid "Permitted"
msgstr "Zugelassen"
#: application/models.py:28 application/templates/application/overview.html:20
-#: application/templates/application/view.html:168
+#: application/templates/application/view.html:175
msgid "Accepted"
msgstr "Angenommen"
#: application/models.py:29 application/templates/application/overview.html:21
-#: application/templates/application/view.html:173
+#: application/templates/application/view.html:180
msgid "Rejected"
msgstr "Abgelehnt"
@@ -474,17 +487,17 @@ msgstr "Abgelehnt"
msgid "Withdrawed"
msgstr "Zurückgezogen"
-#: application/models.py:31 application/templates/application/view.html:181
+#: application/models.py:31 application/templates/application/view.html:188
msgid "Adjourned"
msgstr "Vertagt"
# please check!
-#: application/models.py:32 application/templates/application/view.html:184
+#: application/models.py:32 application/templates/application/view.html:191
msgid "Not Concerned"
msgstr "Nicht befasst"
# please check!
-#: application/models.py:33 application/templates/application/view.html:187
+#: application/models.py:33 application/templates/application/view.html:194
msgid "Commited a bill"
msgstr "Verwiesen (in Ausschuss)"
@@ -492,84 +505,89 @@ msgstr "Verwiesen (in Ausschuss)"
msgid "Rejected (not permitted)"
msgstr "Verworfen (nicht zulässig)"
-#: application/models.py:116
+#: application/models.py:117
msgid "Searching for supporters."
msgstr "Auf Unterstützersuche."
-#: application/models.py:118
+#: application/models.py:119
msgid "Not yet permitted."
msgstr "Noch nicht zugelassen."
-#: application/models.py:120
+#: application/models.py:121
msgid "Not yet permitted changes."
msgstr "Noch nicht zugelassene Änderungen."
#: application/models.py:181
#, python-format
+msgid "Version %s modified"
+msgstr "Version %s bearbeitet"
+
+#: application/models.py:190
+#, python-format
msgid "Version %s created"
msgstr "Version %s erstellt"
-#: application/models.py:190
+#: application/models.py:199
msgid "Supporters removed"
msgstr "Unterstützer/innen gelöscht"
-#: application/models.py:199
+#: application/models.py:208
#, python-format
msgid "Status reseted to: %s"
msgstr "Status zurückgesetzt auf: %s"
-#: application/models.py:212 application/views.py:149
+#: application/models.py:221 application/views.py:157
#, python-format
msgid "Supporter: +%s"
msgstr "Unterstützer/in: +%s"
-#: application/models.py:222 application/views.py:160
+#: application/models.py:231 application/views.py:168
#, python-format
msgid "Supporter: -%s"
msgstr "Unterstützer/in: -%s"
-#: application/models.py:238
+#: application/models.py:247
#, python-format
msgid "Number set: %s"
msgstr "Nummer gesetzt: %s"
-#: application/models.py:251
+#: application/models.py:260
#, python-format
msgid "Version %s permitted"
msgstr "Version %s zugelassen"
-#: application/models.py:265
+#: application/models.py:274
#, python-format
msgid "Version %s not permitted"
msgstr "Version %s nicht zugelassen"
-#: application/models.py:291
+#: application/models.py:300
msgid "Status modified"
msgstr "Status geändert"
-#: application/models.py:407
+#: application/models.py:419
msgid "Poll created"
msgstr "Abstimmung erstellt"
-#: application/views.py:102
+#: application/views.py:110
msgid "You have not the necessary rights to create or edit applications."
msgstr ""
"Sie haben nicht die nötigen Rechte, um Anträge zu erstellen oder zu "
"bearbeiten."
-#: application/views.py:107
+#: application/views.py:115
msgid "You can not edit this application. You are not the submitter."
msgstr "Sie dürfen keine Anträge von anderen bearbeiten."
-#: application/views.py:162
+#: application/views.py:170
msgid "New application was successfully created."
msgstr "Neuer Antrag wurde erfolgreich angelegt."
-#: application/views.py:164
+#: application/views.py:172
msgid "Application was successfully modified."
msgstr "Antrag wurde erfolgreich geändert."
-#: application/views.py:176
+#: application/views.py:184
msgid ""
"Attention: Do you really want to edit this application? The supporters will "
"not be removed automatically because you can manage applications. "
@@ -579,7 +597,7 @@ msgstr ""
"werden nicht automatisch entfernt, da Sie Anträge verwalten dürfen. "
"Prüfen Sie, ob die Unterstützungen noch gültig sind."
-#: application/views.py:178
+#: application/views.py:186
#, python-format
msgid ""
"Attention: Do you really want to edit this application? All %s "
@@ -588,86 +606,140 @@ msgstr ""
"Wollen Sie den Antrag wirklich ändern? Alle %s Unterstützer/innen "
"werden dann automatisch entfernt. Versuchen Sie diese erneut zu gewinnen."
-#: application/views.py:208
+#: application/views.py:216
#, python-format
msgid "You can not delete application %s."
msgstr "Sie können Antrag %s nicht löschen."
-#: application/views.py:214
+#: application/views.py:222
#, python-format
msgid "Application %s was successfully deleted."
msgstr "Antrag %s wurde erfolgreich gelöscht."
-#: application/views.py:230
+#: application/views.py:238
msgid "Application number was successfully set."
msgstr "Antragsnummer wurde erfolgreich gesetzt."
-#: application/views.py:246
+#: application/views.py:254
msgid "Application was successfully permitted."
msgstr "Antrag wurde erfolgreich zugelassen."
-#: application/views.py:259
+#: application/views.py:267
msgid "Application was successfully rejected."
msgstr "Antrag wurde erfolgreich verworfen."
-#: application/views.py:273
+#: application/views.py:281
#, python-format
msgid "Application status was set to: %s."
msgstr "Antragsstatus wurde gesetzt auf: %s"
-#: application/views.py:287
+#: application/views.py:295
msgid "Application status was reset."
msgstr "Antragsstatus wurde zurückgesetzt."
-#: application/views.py:301
+#: application/views.py:309
msgid "You have support the application successfully."
msgstr "Sie haben den Antrag erfolgreich unterstützt."
-#: application/views.py:315
+#: application/views.py:323
msgid "You have unsupport the application successfully."
msgstr "Sie haben dem Antrag erfolgreich Ihre Unterstützung entzogen."
-#: application/views.py:329
+#: application/views.py:344
msgid "New vote was successfully created."
msgstr "Neue Abstimmung erfolgreich angelegt."
-#: application/views.py:345
+#: application/views.py:360
msgid "Poll was successfully deleted."
msgstr "Abstimmung wurde erfolgreich gelöscht."
-#: application/views.py:347
+#: application/views.py:362
#, python-format
msgid "the %s. poll"
msgstr "die %s. Abstimmung"
-#: application/views.py:377 assignment/views.py:220
+#: application/views.py:392 assignment/views.py:227
msgid "Votes are successfully saved."
msgstr "Stimmen erfolgreich gespeichert."
-#: application/views.py:401
+#: application/views.py:416
#, python-format
msgid "Version %s accepted."
msgstr "Version %s akzeptiert."
-#: application/views.py:403
+#: application/views.py:418
#, python-format
msgid "Do you really want to permit version %s?"
msgstr "Soll Version %s wirklich zugelassen werden?"
-#: application/views.py:413
+#: application/views.py:428
#, python-format
msgid "Version %s rejected."
msgstr "Version %s zurückgewiesen."
-#: application/views.py:415
+#: application/views.py:430
msgid "ERROR by rejecting the version."
msgstr "FEHLER beim Zurückweisen der Version."
-#: application/views.py:417
+#: application/views.py:432
#, python-format
msgid "Do you really want to reject version %s?"
msgstr "Soll Version %s wirklich zurückgewiesen werden?"
+#: application/views.py:441 participant/views.py:272
+msgid ""
+"The import function is available for the superuser (without user profile) "
+"only."
+msgstr ""
+"Die Importfunktion ist nur für den 'superuser' (ohne Nutzerprofil) verfügbar."
+
+#: application/views.py:458 application/views.py:462 application/views.py:468
+#: application/views.py:471
+#, python-format
+msgid "Ignoring malformed line %d in import file."
+msgstr "Fehlerhafte Zeile %d der Quelldatei wurde ignoriert."
+
+#: application/views.py:520
+#, python-format
+msgid "%d application was successfully imported."
+msgid_plural "%d applications were successfully imported."
+msgstr[0] "%d Antrag wurde erfolgreich importiert."
+msgstr[1] "%d Anträge wurden erfolgreich importiert."
+
+#: application/views.py:523
+#, python-format
+msgid "%d application was successfully modified."
+msgid_plural "%d applications were successfully modified."
+msgstr[0] "%d Antrag wurde erfolgreich geändert."
+msgstr[1] "%d Anträge wurden erfolgreich geändert."
+
+#: application/views.py:526
+#, python-format
+msgid "%d new user was added."
+msgid_plural "%d new users were added."
+msgstr[0] "%d neuer Nutzer wurde erstellt."
+msgstr[1] "%d neue Nutzer wurden erstellt."
+
+#: application/views.py:530
+msgid "Import aborted because of severe errors in the input file."
+msgstr "Import auf Grund von schweren Fehlern in der Quelldatei abgebrochen."
+
+#: application/views.py:534
+msgid ""
+"Attention: Existing applications will be modified if you import new "
+"applications with the same number."
+msgstr ""
+"Achtung: Existierende Anträge werden geändert wenn Sie neue Anträge mit "
+"identischer Nummer importieren."
+
+#: application/views.py:535
+msgid ""
+"Attention: Importing an application without a number multiple times will "
+"create duplicates."
+msgstr ""
+"Achtung: Bei mehrfachem Import eines Antrags ohne Nummer können Duplikate "
+"entstehen."
+
#: application/templates/application/base_application.html:6
#: application/templates/application/overview.html:2
#: application/templates/application/overview.html:6
@@ -685,7 +757,12 @@ msgstr "Alle Anträge"
msgid "New application"
msgstr "Neuer Antrag"
-#: application/templates/application/base_application.html:12
+#: application/templates/application/base_application.html:11
+#: application/templates/application/import.html:2
+msgid "Import applications"
+msgstr "Anträge importieren"
+
+#: application/templates/application/base_application.html:13
msgid "Print all applications"
msgstr "Alle Anträge drucken"
@@ -697,6 +774,25 @@ msgstr "Antrag bearbeiten"
msgid "required"
msgstr "erforderlich"
+#: application/templates/application/import.html:6
+msgid "Select a CSV file to import applications!"
+msgstr "Wählen Sie eine CSV-Datei zum Importieren von Anträgen aus!"
+
+#: application/templates/application/import.html:8
+msgid ""
+"(Required comma separated values: number, title, text, reason, "
+"first_name, last_name
- number
and reason
"
+"are optional and may be empty)"
+msgstr ""
+"(Erfordert kommaseparierte Werte: Nummer, Titel, Text, Begründung, "
+"Vorname, Nachname
- Nummer
und Begründung
"
+"sind optional und können auch leer sein)"
+
+#: application/templates/application/import.html:12
+#: participant/templates/participant/import.html:12
+msgid "Import"
+msgstr "Importiern"
+
#: application/templates/application/overview.html:8
#: assignment/templates/assignment/overview.html:8
#: participant/templates/participant/overview.html:9
@@ -850,70 +946,76 @@ msgstr "Setze Nummer"
msgid "New agenda item"
msgstr "Neuer Tagesordnungseintrag"
-#: application/templates/application/view.html:165
+#: application/templates/application/view.html:167
+#: assignment/templates/assignment/view.html:48
+#, fuzzy
+msgid "Show agenda item"
+msgstr "Neuer Tagesordnungseintrag"
+
+#: application/templates/application/view.html:172
msgid "Result after vote"
msgstr "Ergebnis nach der Abstimmung"
-#: application/templates/application/view.html:179
+#: application/templates/application/view.html:186
msgid "Result after debate"
msgstr "Ergebnis nach der Debatte"
-#: application/templates/application/view.html:190
+#: application/templates/application/view.html:197
msgid "Withdrawed by Submitter"
msgstr "Zurückgezogen durch Antragsteller/in"
-#: application/templates/application/view.html:196
+#: application/templates/application/view.html:203
msgid "For Administration only:"
msgstr "Nur zur Administration:"
-#: application/templates/application/view.html:198
+#: application/templates/application/view.html:205
msgid "Reset"
msgstr "Zurücksetzen"
-#: application/templates/application/view.html:216
-#: application/templates/application/view.html:244
+#: application/templates/application/view.html:223
+#: application/templates/application/view.html:251
msgid "Version"
msgstr "Version"
-#: application/templates/application/view.html:219
+#: application/templates/application/view.html:226
msgid "Show newest Version"
msgstr "Neuste Version anzeigen"
-#: application/templates/application/view.html:221
+#: application/templates/application/view.html:228
msgid "Show permitted Version"
msgstr "Zugelassene Version anzeigen"
-#: application/templates/application/view.html:239
+#: application/templates/application/view.html:246
msgid "Version History"
msgstr "Versionshistorie"
-#: application/templates/application/view.html:245
+#: application/templates/application/view.html:252
msgid "Time"
msgstr "Zeit"
-#: application/templates/application/view.html:256
+#: application/templates/application/view.html:263
msgid "Version accepted"
msgstr "Version akzeptiert"
-#: application/templates/application/view.html:259
+#: application/templates/application/view.html:266
msgid "Accept Version"
msgstr "Zugelassene Version"
-#: application/templates/application/view.html:262
+#: application/templates/application/view.html:269
msgid "Reject Version"
msgstr "Verion zurückweisen"
-#: application/templates/application/view.html:266
+#: application/templates/application/view.html:273
msgid "Version rejected"
msgstr "Version zurückgewiesen"
-#: application/templates/application/view.html:276
#: application/templates/application/view.html:283
#: application/templates/application/view.html:290
+#: application/templates/application/view.html:297
msgid "unchanged"
msgstr "unverändert"
-#: application/templates/application/view.html:299
+#: application/templates/application/view.html:306
msgid "Log"
msgstr "Log"
@@ -967,84 +1069,84 @@ msgstr "%s ist bereits ein/e Kandidat/in."
msgid "%s is no candidate"
msgstr "%s ist kein/e Kandidat/in"
-#: assignment/views.py:61
+#: assignment/views.py:62
#, python-format
msgid "Candidate %s was nominated successfully."
msgstr "Kandidat/in %s wurde erfolgreich vorgeschlagen."
-#: assignment/views.py:109
+#: assignment/views.py:110
msgid "New election was successfully created."
msgstr "Neue Wahl wurde erfolgreich angelegt."
-#: assignment/views.py:111
+#: assignment/views.py:112
msgid "Election was successfully modified."
msgstr "Wahl wurde erfolgreich geändert."
-#: assignment/views.py:129
+#: assignment/views.py:130
#, python-format
msgid "Election %s was successfully deleted."
msgstr "Wahl %s wurde erfolgreich gelöscht."
-#: assignment/views.py:142
+#: assignment/views.py:143
#, python-format
msgid "Election status was set to: %s."
msgstr "Wahlstatus wurde gesetzt auf: %s."
-#: assignment/views.py:153
+#: assignment/views.py:154
msgid "You have set your candidature successfully."
msgstr "Sie haben Ihre Kandidatur erfolgreich gesetzt."
-#: assignment/views.py:158
+#: assignment/views.py:159
msgid "You can't candidate. Your user account is only for administration."
msgstr ""
"Sie können nicht kandidieren. Ihr Nutzerkonto ist nur zur Administration."
-#: assignment/views.py:166
+#: assignment/views.py:167
msgid "You have withdrawn your candidature successfully."
msgstr "Sie haben Ihre Kandidatur erfolgreich zurückgezogen."
-#: assignment/views.py:177
+#: assignment/views.py:178
#, python-format
msgid "Candidate %s was withdrawn successfully."
msgstr "Die Kandidatur von %s wurde erfolgreich zurückgezogen."
-#: assignment/views.py:180
+#: assignment/views.py:181
#, python-format
msgid "Do you really want to withdraw %s from the election?"
msgstr "Soll %s wirklich von der Wahl zurückgezogen werden?"
-#: assignment/views.py:189
+#: assignment/views.py:196
msgid "New ballot was successfully created."
msgstr "Neuer Wahlgang erfolgreich angelegt."
-#: assignment/views.py:244
+#: assignment/views.py:251
msgid "Poll successfully set to published."
msgstr "Abstimmung wurde erfolgreich veröffentlicht."
-#: assignment/views.py:246
+#: assignment/views.py:253
msgid "Poll successfully set to unpublished."
msgstr "Abstimmung wurde erfolgreich unveröffentlicht."
-#: assignment/views.py:248
+#: assignment/views.py:255
#, python-format
msgid "Poll ID %d does not exist."
msgstr "Abstimmungs-ID %d existiert nicht."
-#: assignment/views.py:258
+#: assignment/views.py:265
#, python-format
msgid "The %s. ballot was successfully deleted."
msgstr "Der %s. Wahlgang wurde erfolgreich gelöscht."
-#: assignment/views.py:260
+#: assignment/views.py:267
#, python-format
msgid "the %s. ballot"
msgstr "der %s. Wahlgang"
-#: assignment/views.py:272
+#: assignment/views.py:279
msgid "not elected"
msgstr "nicht gewählt"
-#: assignment/views.py:275 utils/pdf.py:623
+#: assignment/views.py:282 utils/pdf.py:623
msgid "elected"
msgstr "gewählt"
@@ -1126,36 +1228,36 @@ msgstr "Status ändern"
msgid "Finish"
msgstr "Abschließen"
-#: assignment/templates/assignment/view.html:61
+#: assignment/templates/assignment/view.html:68
msgid "Remove candidate"
msgstr "Kandidate/in entfernen"
-#: assignment/templates/assignment/view.html:79
+#: assignment/templates/assignment/view.html:86
msgid "Withdraw self candidature"
msgstr "Eigene Kandidatur zurückziehen"
-#: assignment/templates/assignment/view.html:86
+#: assignment/templates/assignment/view.html:93
msgid "Self candidature"
msgstr "Selbst kandidieren"
-#: assignment/templates/assignment/view.html:98
+#: assignment/templates/assignment/view.html:105
msgid "Add new participant"
msgstr "Neue/n Teilnehmer/in hinzufügen"
-#: assignment/templates/assignment/view.html:136
+#: assignment/templates/assignment/view.html:143
msgid "Unpublish results"
msgstr "Ergebnisse unveröffentlichen"
-#: assignment/templates/assignment/view.html:140
+#: assignment/templates/assignment/view.html:147
msgid "Publish results"
msgstr "Ergebnisse veröffentlichen"
-#: assignment/templates/assignment/view.html:142
+#: assignment/templates/assignment/view.html:149
msgid "Delete Poll"
msgstr "Abstimmung löschen"
-#: assignment/templates/assignment/view.html:151
-#: assignment/templates/assignment/view.html:225
+#: assignment/templates/assignment/view.html:158
+#: assignment/templates/assignment/view.html:232
msgid "New ballot"
msgstr "Neuer Wahlgang"
@@ -1167,10 +1269,6 @@ msgstr "Vorname"
msgid "Last name"
msgstr "Nachname"
-#: participant/forms.py:72
-msgid "CSV File"
-msgstr "CSV-Datei"
-
#: participant/models.py:22 participant/templates/participant/overview.html:14
msgid "Not specified"
msgstr "Nicht angegeben"
@@ -1271,13 +1369,6 @@ msgstr "Gruppe %s wurde erfolgreich gelöscht."
msgid "User settings successfully saved."
msgstr "Nutzereinstellungen wurden erfolgreich gespeichert."
-#: participant/views.py:272
-msgid ""
-"The import function is available for the superuser (without user profile) "
-"only."
-msgstr ""
-"Die Importfunktion ist nur für den 'superuser' (ohne Nutzerprofil) verfügbar."
-
#: participant/views.py:311
#, python-format
msgid "%d new participants were successfully imported."
@@ -1417,10 +1508,6 @@ msgstr ""
"(Erfordert kommaseparierte Werte: Vorname, Nachname, Geschlecht, "
"Gruppe, Typ, Amt
)"
-#: participant/templates/participant/import.html:12
-msgid "Import"
-msgstr "Importiern"
-
#: participant/templates/participant/login.html:5
#: participant/templates/participant/login.html:13
#: participant/templates/participant/login.html:43 templates/base.html:26