From 07a83f142b740160db41bc870d3511777f82c538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rene=CC=81=20Ko=CC=88cher?= Date: Wed, 11 Apr 2012 14:49:24 +0200 Subject: [PATCH] #84: Participants CSV import deletes applications --- openslides/application/models.py | 6 + .../templates/application/overview.html | 1 + .../templates/application/view.html | 5 +- openslides/locale/de/LC_MESSAGES/django.mo | Bin 28129 -> 30044 bytes openslides/locale/de/LC_MESSAGES/django.po | 229 ++++++++++++------ openslides/participant/forms.py | 9 +- openslides/participant/views.py | 79 ++++++ 7 files changed, 248 insertions(+), 81 deletions(-) diff --git a/openslides/application/models.py b/openslides/application/models.py index 0cedf991b..fb5404816 100644 --- a/openslides/application/models.py +++ b/openslides/application/models.py @@ -33,6 +33,7 @@ class Application(models.Model): ('noc', _('Not Concerned')), ('com', _('Commited a bill')), ('nop', _('Rejected (not permitted)')), + ('rev', _('Needs Review')), #additional actions: # edit # delete @@ -319,6 +320,11 @@ class Application(models.Model): or (self.status == "per" \ and user.has_perm("application.can_manage_application")): actions.append("wit") + #Check if the user can review the application + if self.status == "rev" \ + and (self.submitter == user \ + or user.has_perm("application.can_manage_application")): + actions.append("pub") try: # Check if the user can support and unspoort the application if self.status == "pub" \ diff --git a/openslides/application/templates/application/overview.html b/openslides/application/templates/application/overview.html index c1a42d47e..ed9a56a34 100644 --- a/openslides/application/templates/application/overview.html +++ b/openslides/application/templates/application/overview.html @@ -20,6 +20,7 @@ +

diff --git a/openslides/application/templates/application/view.html b/openslides/application/templates/application/view.html index 1e68decab..21ab53c79 100644 --- a/openslides/application/templates/application/view.html +++ b/openslides/application/templates/application/view.html @@ -140,8 +140,11 @@

{% trans "Manage application" %}

- {% if "per" in actions or "nop" in actions or "setnumber" in actions %} + {% if "pub" in actions or "per" in actions or "nop" in actions or "setnumber" in actions %}

{% trans "Formal validation" %}:

+ {% if "pub" in actions %} + {% trans 'Publish' %} + {% endif %} {% if "per" in actions %} {% trans 'Permit' %} {% endif %} diff --git a/openslides/locale/de/LC_MESSAGES/django.mo b/openslides/locale/de/LC_MESSAGES/django.mo index d75ab93e644b599a0e4237d729f6e9b821d3712e..0b96e3e243495743599cd6c4226874dbd4ec12c5 100644 GIT binary patch delta 10263 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\n" "Language-Team: LANGUAGE \n" @@ -53,8 +53,8 @@ msgstr "Nein" msgid "Yes, with all child items." msgstr "Ja, mit allen Kindelementen." -#: agenda/api.py:71 agenda/api.py:73 participant/views.py:192 -#: participant/views.py:305 utils/utils.py:40 +#: agenda/api.py:71 agenda/api.py:73 participant/views.py:193 +#: participant/views.py:306 utils/utils.py:40 #, python-format msgid "Do you really want to delete %s?" msgstr "Soll %s wirklich gelöscht werden?" @@ -64,7 +64,7 @@ msgid "Parent item" msgstr "Elternelement" #: agenda/models.py:35 application/forms.py:41 -#: application/templates/application/view.html:250 +#: 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:251 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:220 #: application/templates/application/edit.html:2 #: application/templates/application/view.html:2 -#: application/templates/application/view.html:217 poll/models.py:23 +#: application/templates/application/view.html:220 poll/models.py:23 #: poll/models.py:138 system/templates/system/base_system.html:14 #: utils/pdf.py:458 utils/pdf.py:470 msgid "Application" @@ -147,8 +147,8 @@ msgid "Agenda item modified" msgstr "Tagesordnungseintrag geändert" #: agenda/views.py:286 application/views.py:181 application/views.py:538 -#: assignment/views.py:118 participant/views.py:169 participant/views.py:290 -#: participant/views.py:319 participant/views.py:389 system/views.py:37 +#: assignment/views.py:118 participant/views.py:170 participant/views.py:291 +#: participant/views.py:320 participant/views.py:465 system/views.py:37 #: system/views.py:59 system/views.py:83 system/views.py:113 #: system/views.py:152 msgid "Please check the form for errors." @@ -373,7 +373,7 @@ msgstr "Keine Einträge vorhanden." #: agenda/templates/beamer/ItemApplication.html:8 #: agenda/templates/beamer/ItemAssignment.html:13 #: application/templates/application/overview.html:16 -#: application/templates/application/overview.html:34 +#: application/templates/application/overview.html:35 #: application/templates/application/view.html:35 #: assignment/templates/assignment/overview.html:10 #: assignment/templates/assignment/overview.html:23 @@ -383,7 +383,7 @@ msgid "Status" msgstr "Status" #: agenda/templates/beamer/ItemApplication.html:19 application/forms.py:51 -#: application/models.py:47 application/templates/application/overview.html:35 +#: application/models.py:48 application/templates/application/overview.html:36 #: application/templates/application/view.html:9 utils/pdf.py:350 msgid "Submitter" msgstr "Antragsteller/in" @@ -436,14 +436,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:215 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:233 -#: application/templates/application/view.html:253 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" @@ -507,12 +507,12 @@ msgstr "Triviale Änderung" msgid "Trivial changes don't create a new version." msgstr "Triviale Änderungen erzeugen keine neue Version." -#: application/forms.py:52 application/models.py:49 +#: application/forms.py:52 application/models.py:50 #: application/templates/application/view.html:23 utils/pdf.py:363 msgid "Supporters" msgstr "Unterstützer/innen" -#: application/forms.py:62 participant/forms.py:93 +#: application/forms.py:62 participant/forms.py:99 msgid "CSV File" msgstr "CSV-Datei" @@ -525,12 +525,12 @@ msgid "Permitted" msgstr "Zugelassen" #: application/models.py:29 application/templates/application/overview.html:20 -#: application/templates/application/view.html:175 +#: application/templates/application/view.html:178 msgid "Accepted" msgstr "Angenommen" #: application/models.py:30 application/templates/application/overview.html:21 -#: application/templates/application/view.html:180 +#: application/templates/application/view.html:183 msgid "Rejected" msgstr "Abgelehnt" @@ -538,17 +538,17 @@ msgstr "Abgelehnt" msgid "Withdrawed" msgstr "Zurückgezogen" -#: application/models.py:32 application/templates/application/view.html:188 +#: application/models.py:32 application/templates/application/view.html:191 msgid "Adjourned" msgstr "Vertagt" # please check! -#: application/models.py:33 application/templates/application/view.html:191 +#: application/models.py:33 application/templates/application/view.html:194 msgid "Not Concerned" msgstr "Nicht befasst" # please check! -#: application/models.py:34 application/templates/application/view.html:194 +#: application/models.py:34 application/templates/application/view.html:197 msgid "Commited a bill" msgstr "Verwiesen (in Ausschuss)" @@ -556,67 +556,71 @@ msgstr "Verwiesen (in Ausschuss)" msgid "Rejected (not permitted)" msgstr "Verworfen (nicht zulässig)" -#: application/models.py:118 +#: application/models.py:36 application/templates/application/overview.html:23 +msgid "Needs Review" +msgstr "Benötigt Review" + +#: application/models.py:119 msgid "Searching for supporters." msgstr "Auf Unterstützersuche." -#: application/models.py:120 +#: application/models.py:121 msgid "Not yet permitted." msgstr "Noch nicht zugelassen." -#: application/models.py:122 +#: application/models.py:123 msgid "Not yet permitted changes." msgstr "Noch nicht zugelassene Änderungen." -#: application/models.py:182 +#: application/models.py:183 #, python-format msgid "Version %s modified" msgstr "Version %s bearbeitet" -#: application/models.py:191 +#: application/models.py:192 #, python-format msgid "Version %s created" msgstr "Version %s erstellt" -#: application/models.py:200 +#: application/models.py:201 msgid "Supporters removed" msgstr "Unterstützer/innen gelöscht" -#: application/models.py:209 +#: application/models.py:210 #, python-format msgid "Status reseted to: %s" msgstr "Status zurückgesetzt auf: %s" -#: application/models.py:222 application/views.py:159 +#: application/models.py:223 application/views.py:159 #, python-format msgid "Supporter: +%s" msgstr "Unterstützer/in: +%s" -#: application/models.py:232 application/views.py:170 +#: application/models.py:233 application/views.py:170 #, python-format msgid "Supporter: -%s" msgstr "Unterstützer/in: -%s" -#: application/models.py:248 +#: application/models.py:249 #, python-format msgid "Number set: %s" msgstr "Nummer gesetzt: %s" -#: application/models.py:261 +#: application/models.py:262 #, python-format msgid "Version %s permitted" msgstr "Version %s zugelassen" -#: application/models.py:275 +#: application/models.py:276 #, python-format msgid "Version %s not permitted" msgstr "Version %s nicht zugelassen" -#: application/models.py:301 +#: application/models.py:302 msgid "Status modified" msgstr "Status geändert" -#: application/models.py:420 +#: application/models.py:426 msgid "Poll created" msgstr "Abstimmung erstellt" @@ -737,7 +741,7 @@ msgstr "FEHLER beim Zurückweisen der Version." msgid "Do you really want to reject version %s?" msgstr "Soll Version %s wirklich zurückgewiesen werden?" -#: application/views.py:444 participant/views.py:335 +#: application/views.py:444 participant/views.py:336 msgid "" "The import function is available for the superuser (without user profile) " "only." @@ -771,7 +775,7 @@ msgid_plural "%d new users were added." msgstr[0] "%d neuer Nutzer wurde erstellt." msgstr[1] "%d neue Nutzer wurden erstellt." -#: application/views.py:536 participant/views.py:387 +#: application/views.py:536 participant/views.py:463 msgid "Import aborted because of severe errors in the input file." msgstr "Import auf Grund von schweren Fehlern in der Quelldatei abgebrochen." @@ -794,7 +798,7 @@ msgstr "" #: application/templates/application/base_application.html:6 #: application/templates/application/overview.html:2 #: application/templates/application/overview.html:6 -#: application/templates/application/overview.html:26 system/models.py:23 +#: application/templates/application/overview.html:27 system/models.py:23 #: templates/base.html:41 utils/pdf.py:429 msgid "Applications" msgstr "Anträge" @@ -867,24 +871,24 @@ msgstr "Noch nicht zugelassen" msgid "Withdrawed (by submitter)" msgstr "Zurückgezogen (durch Antragsteller/in)" -#: application/templates/application/overview.html:29 +#: application/templates/application/overview.html:30 msgid "Number" msgstr "Nummer" -#: application/templates/application/overview.html:30 +#: application/templates/application/overview.html:31 msgid "Application title" msgstr "Antragstitel" -#: application/templates/application/overview.html:32 +#: application/templates/application/overview.html:33 msgid "Number of supporters" msgstr "Anzahl der Unterstützer/innen" -#: application/templates/application/overview.html:36 +#: application/templates/application/overview.html:37 #: application/templates/application/view.html:102 msgid "Creation Time" msgstr "Erstellungszeit" -#: application/templates/application/overview.html:58 +#: application/templates/application/overview.html:59 msgid "No applications available." msgstr "Keine Anträge vorhanden." @@ -982,91 +986,95 @@ msgid "Formal validation" msgstr "Formale Gültigkeitsprüfung" #: application/templates/application/view.html:146 +msgid "Publish" +msgstr "Veröffentlichen" + +#: application/templates/application/view.html:149 msgid "Permit" msgstr "Zulassen" -#: application/templates/application/view.html:149 +#: application/templates/application/view.html:152 msgid "Not permit (reject)" msgstr "Nicht zulassen (verwerfen)" -#: application/templates/application/view.html:152 +#: application/templates/application/view.html:155 msgid "Set Number" msgstr "Setze Nummer" -#: application/templates/application/view.html:160 +#: application/templates/application/view.html:163 #: assignment/templates/assignment/view.html:43 msgid "New agenda item" msgstr "Neuer Tagesordnungseintrag" -#: application/templates/application/view.html:167 +#: application/templates/application/view.html:170 #: assignment/templates/assignment/view.html:50 msgid "Show agenda item" msgstr "Zeige Tagesordnungseintrag" -#: application/templates/application/view.html:172 +#: application/templates/application/view.html:175 msgid "Result after vote" msgstr "Ergebnis nach der Abstimmung" -#: application/templates/application/view.html:186 +#: application/templates/application/view.html:189 msgid "Result after debate" msgstr "Ergebnis nach der Debatte" -#: application/templates/application/view.html:197 +#: application/templates/application/view.html:200 msgid "Withdrawed by Submitter" msgstr "Zurückgezogen durch Antragsteller/in" -#: application/templates/application/view.html:203 +#: application/templates/application/view.html:206 msgid "For Administration only:" msgstr "Nur zur Administration:" -#: application/templates/application/view.html:205 +#: application/templates/application/view.html:208 msgid "Reset" msgstr "Zurücksetzen" -#: application/templates/application/view.html:220 -#: application/templates/application/view.html:248 +#: application/templates/application/view.html:223 +#: application/templates/application/view.html:251 msgid "Version" msgstr "Version" -#: application/templates/application/view.html:223 +#: application/templates/application/view.html:226 msgid "Show newest Version" msgstr "Neuste Version anzeigen" -#: application/templates/application/view.html:225 +#: application/templates/application/view.html:228 msgid "Show permitted Version" msgstr "Zugelassene Version anzeigen" -#: application/templates/application/view.html:243 +#: application/templates/application/view.html:246 msgid "Version History" msgstr "Versionshistorie" -#: application/templates/application/view.html:249 +#: application/templates/application/view.html:252 msgid "Time" msgstr "Zeit" -#: application/templates/application/view.html:260 +#: application/templates/application/view.html:263 msgid "Version accepted" msgstr "Version akzeptiert" -#: application/templates/application/view.html:263 +#: application/templates/application/view.html:266 msgid "Accept Version" msgstr "Zugelassene Version" -#: application/templates/application/view.html:266 +#: application/templates/application/view.html:269 msgid "Reject Version" msgstr "Verion zurückweisen" -#: application/templates/application/view.html:270 +#: application/templates/application/view.html:273 msgid "Version rejected" msgstr "Version zurückgewiesen" -#: application/templates/application/view.html:280 -#: application/templates/application/view.html:287 -#: application/templates/application/view.html:294 +#: 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:303 +#: application/templates/application/view.html:306 msgid "Log" msgstr "Log" @@ -1311,14 +1319,30 @@ msgstr "Abstimmung löschen" msgid "New ballot" msgstr "Neuer Wahlgang" -#: participant/forms.py:37 participant/forms.py:48 +#: participant/forms.py:34 +msgid "Keep applications, try to reassign submitter" +msgstr "Anträge beibehalten, versuchen Antragssteller erneut zuzuweisen" + +#: participant/forms.py:35 +msgid "Keep applications, set status to \"needs review\"" +msgstr "Anträge beibehalten, Stauts auf \"Benötigt Review\" setzen" + +#: participant/forms.py:36 +msgid "Discard applications" +msgstr "Alle Anträge löschen" + +#: participant/forms.py:43 participant/forms.py:54 msgid "First name" msgstr "Vorname" -#: participant/forms.py:38 participant/forms.py:49 +#: participant/forms.py:44 participant/forms.py:55 msgid "Last name" msgstr "Nachname" +#: participant/forms.py:100 +msgid "For existing applications" +msgstr "Bei existierenden Anträgen" + #: participant/models.py:22 participant/templates/participant/overview.html:19 msgid "Male" msgstr "Männlich" @@ -1369,51 +1393,86 @@ msgstr "Kommentar" msgid "First Password" msgstr "Erst-Passwort" -#: participant/views.py:161 +#: participant/views.py:162 msgid "New participant was successfully created." msgstr "Neue/r Teilnehmer/in wurde erfolgreich angelegt." -#: participant/views.py:163 +#: participant/views.py:164 msgid "Participant was successfully modified." msgstr "Teilnehmer/in wurde erfolgreich geändert." -#: participant/views.py:190 +#: participant/views.py:191 #, python-format msgid "Participant %s was successfully deleted." msgstr "Teilnehmer/in %s wurde erfolgreich gelöscht." -#: participant/views.py:203 participant/views.py:222 +#: participant/views.py:204 participant/views.py:223 +#, python-format msgid "Participant %d does not exist." msgstr "Teinehmer/in %d existiert nicht." -#: participant/views.py:268 +#: participant/views.py:269 #, python-format msgid "Group name \"%s\" is reserved for internal use." msgstr "Der Gruppenname \"%s\" ist für interne Verwendung reserviert." -#: participant/views.py:282 +#: participant/views.py:283 msgid "New group was successfully created." msgstr "Neue Gruppe wurde erfolgreich angelegt." -#: participant/views.py:284 +#: participant/views.py:285 msgid "Group was successfully modified." msgstr "Gruppe wurde erfolgreich geändert." -#: participant/views.py:303 +#: participant/views.py:304 #, python-format msgid "Group %s was successfully deleted." msgstr "Gruppe %s wurde erfolgreich gelöscht." -#: participant/views.py:317 +#: participant/views.py:318 msgid "User settings successfully saved." msgstr "Nutzereinstellungen wurden erfolgreich gespeichert." #: participant/views.py:384 +msgid "Supporters removed after user import." +msgstr "Unterstützer/innen nach Benutzerimport zurückgesetzt." + +#: participant/views.py:431 +#, python-format +msgid "Reassigned to \"%s\" after (re)importing users." +msgstr "Nach Benutzerimport erneut \"%s\" zugeordnet." + +#: participant/views.py:434 participant/views.py:448 +#, python-format +msgid "Could not reassing application %d - object not found!" +msgstr "Antrag Id#%d konnte nicht neu zugewiesen werden - " +"Das Objekt wurde nicht gefunden!" + +#: participant/views.py:451 +#, python-format +msgid "%d application could not be reassigned and needs a review!" +msgid_plural "%d applications could not be reassigned and need a review!" +msgstr[0] "%d Antrag konnte nicht neu zugewiesen werden and benötigt ein Review!" +msgstr[1] "%d Anträge konnten nicht neu zugewiesen werden und benötigen ein Review!" + +#: participant/views.py:454 +msgid "%d application was successfully reassigned." +msgid_plural "%d applications were successfully reassigned." +msgstr[0] "%d Antrag wurde erfolgreich neu zugewiesen." +msgstr[1] "%d Anträge wurden erfolgreich neu zugewiesen." + +#: participant/views.py:457 +msgid "%d application was discarded." +msgid_plural "%d applications were discarded." +msgstr[0] "%d Antrag wurde gelöscht." +msgstr[1] "%d Anträge wurden gelöscht." + +#: participant/views.py:460 #, python-format msgid "%d new participants were successfully imported." msgstr "%d neue Teilnehmer/innen wurden erfolgreich importiert." -#: participant/views.py:391 +#: participant/views.py:467 msgid "" "Attention: All existing participants will be removed if you import new " "participants." @@ -1421,12 +1480,24 @@ msgstr "" "Achtung: Alle existierenden Teilnehmer/innen werden gelöscht, wenn Sie neue " "Teilnehmer/innen importieren." -#: participant/views.py:403 +#: participant/views.py:469 +msgid "Attention: Supporters from all existing applications will be removed." +msgstr "" +"Achtung: Alle Unterstützer/innen werden von existiernden Anträgen gelöscht." + +#: participant/views.py:470 +msgid "" +"Attention: Applications which can't be mapped to new users will be set to " +"'Needs Review'." +msgstr "Achtung: Anträge welche keinem Nutzer zugeordnet werden können" +" bekommen automatisch den Status \"Benötigt Review\"." + +#: participant/views.py:482 #, python-format msgid "The Password for %s was successfully reset." msgstr "Das Passwort für %s wurde erfolgreich zurückgesetzt." -#: participant/views.py:405 +#: participant/views.py:484 #, python-format msgid "Do you really want to reset the password for %s?" msgstr "Soll das Passwort für %s wirklich zurückgesetzt werden?" diff --git a/openslides/participant/forms.py b/openslides/participant/forms.py index c9c099e46..a212ae559 100644 --- a/openslides/participant/forms.py +++ b/openslides/participant/forms.py @@ -10,7 +10,7 @@ :license: GNU GPL, see LICENSE for more details. """ -from django.forms import Form, ModelForm, CharField, EmailField, FileField, FileInput, MultipleChoiceField, ModelMultipleChoiceField +from django.forms import Form, ModelForm, CharField, EmailField, FileField, FileInput, MultipleChoiceField, ModelMultipleChoiceField, ChoiceField, BooleanField from django.contrib.auth.models import User, Group, Permission from django.contrib.auth.forms import AdminPasswordChangeForm from django.utils.translation import ugettext as _ @@ -30,6 +30,12 @@ USER_VISIBLE_PERMISSIONS = reduce(list.__add__, [ [p[0] for p in Config._meta.permissions] ]) +USER_APPLICATION_IMPORT_OPTIONS = [ + ('REASSIGN', _('Keep applications, try to reassign submitter')), + ('INREVIEW', _('Keep applications, set status to "needs review"')), + ('DISCARD' , _('Discard applications')) +] + class UserNewForm(ModelForm): error_css_class = 'error' required_css_class = 'required' @@ -91,3 +97,4 @@ class UserImportForm(Form): required_css_class = 'required' csvfile = FileField(widget=FileInput(attrs={'size':'50'}), label=_("CSV File")) + application_handling = ChoiceField(required=True, choices=USER_APPLICATION_IMPORT_OPTIONS, label=_("For existing applications")) diff --git a/openslides/participant/views.py b/openslides/participant/views.py index 958f5be40..91d73807d 100644 --- a/openslides/participant/views.py +++ b/openslides/participant/views.py @@ -34,6 +34,7 @@ from django.db import transaction from participant.models import Profile from participant.api import gen_username, gen_password from participant.forms import UserNewForm, UserEditForm, ProfileForm, UsersettingsForm, UserImportForm, GroupForm, AdminPasswordChangeForm +from application.models import Application from utils.utils import template, permission_required, gen_confirm_form, ajax_request from utils.pdf import print_userlist, print_passwords from system.api import config_get @@ -345,6 +346,43 @@ def user_import(request): if form.is_valid(): try: with transaction.commit_on_success(): + + old_users = {} + applications_mapped = 0 + applications_review = 0 + applications_removed = 0 + + try: + janitor = User.objects.get(username='__system__.janitor') + except User.DoesNotExist: + janitor = User() + janitor.first_name = '' + janitor.last_name = '' + janitor.username = '__system__.janitor' + janitor.save() + + applications = Application.objects.all() + for application in applications: + if form.cleaned_data['application_handling'] == 'DISCARD': + # need to do this explicit since some applications may belong + # to __system__.janitor which is a permanent user + application.delete(force=True) + applications_removed += 1 + else: + # collect all applications and map them to their submitters + submitter = application.submitter + skey = '%s_%s' % (submitter.first_name, submitter.last_name) + + if not skey in old_users: + old_users[skey] = [] + old_users[skey].append(application.id) + + application.submitter = janitor + application.save() + + if application.supporter.all(): + application.writelog(_('Supporters removed after user import.'), user=request.user) + profiles = Profile.objects.all() for profile in profiles: profile.user.delete() @@ -381,6 +419,44 @@ def user_import(request): observer = Group.objects.get(name='Beobachter') user.groups.add(observer) + if form.cleaned_data['application_handling'] == 'REASSIGN': + # live remap + skey = '%s_%s' % (user.first_name, user.last_name) + if skey in old_users: + for appid in old_users[skey]: + try: + application = Application.objects.get(id=appid) + application.submitter = user + application.save() + application.writelog(_('Reassigned to "%s" after (re)importing users.') % ("%s %s" % (user.first_name, user.last_name)), user=request.user) + applications_mapped += 1 + except Application.DoesNotExist: + messages.error(request, _('Could not reassing application %d - object not found!') % appid) + del old_users[skey] + + if old_users: + # mark all applications without a valid user as 'needs review' + # this will account for *all* applications if application_mode == 'INREVIEW' + for skey in old_users: + for appid in old_users[skey]: + try: + application = Application.objects.get(id=appid) + if application.status != 'rev': + application.set_status(user=request.user, status='rev', force=True) + applications_review += 1 + except Application.DoesNotExist: + messages.error(request, _('Could not reassing application %d - object not found!') % appid) + + if applications_review: + messages.warning(request, ungettext('%d application could not be reassigned and needs a review!', + '%d applications could not be reassigned and need a review!', applications_review) % applications_review) + if applications_mapped: + messages.success(request, ungettext('%d application was successfully reassigned.', + '%d applications were successfully reassigned.', applications_mapped) % applications_mapped) + if applications_removed: + messages.warning(request, ungettext('%d application was discarded.', + '%d applications were discarded.', applications_removed) % applications_removed) + messages.success(request, _('%d new participants were successfully imported.') % i) return redirect(reverse('user_overview')) except csv.Error: @@ -389,6 +465,9 @@ def user_import(request): messages.error(request, _('Please check the form for errors.')) else: messages.warning(request, _("Attention: All existing participants will be removed if you import new participants.")) + if Application.objects.all(): + messages.warning(request, _("Attention: Supporters from all existing applications will be removed.")) + messages.warning(request, _("Attention: Applications which can't be mapped to new users will be set to 'Needs Review'.")) form = UserImportForm() return { 'form': form,