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)' %}

    +
    {% csrf_token %} + {{ form.as_p }} + + + + +
    +

    +{% 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