Commit 24a36392 authored by Staś Kycia's avatar Staś Kycia
Browse files

entering local votes for hybrid elections

parent a225bf5d
Loading
Loading
Loading
Loading
+87 −2
Changes for hybrid/admin.py: 87 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -14,7 +14,8 @@ from django.utils.decorators import method_decorator
from elections.models import Election
from voters.models import Voter
from vote.models import Participation
from .models import HybridElectionVoter
from .models import HybridElectionVoter, EnterHybridVotesElection
from .forms import LocalVotesForm

class ElectionContextFilter(admin.SimpleListFilter):
    title = 'wybory'
@@ -86,7 +87,6 @@ class HybridElectionVoterAdmin(admin.ModelAdmin):
            return None
        card_issuer = queryset.first().card_issued_by
        return f'{card_issuer.first_name} {card_issuer.last_name} ({card_issuer.username})'
        return 'zad'
    
    def get_urls(self):
        urls = super().get_urls()
@@ -135,4 +135,89 @@ class HybridElectionVoterAdmin(admin.ModelAdmin):
    def has_delete_permission(self, request, obj = None):
        return False
    
class EnterHybridVotesElectionAdmin(admin.ModelAdmin):
    list_display = ['name', 'start_date', 'end_date', 'local_votes_action']
    ordering = ['-created_at', '-updated_at']

    exclude = ['invalid_votes', 'local_votes_entered']
    
    @admin.display(description='Głosy stacjonarne')
    def local_votes_action(self, obj):
        if not obj.is_hybrid or obj.is_active:
            return None
        
        if obj.local_votes_entered:
            return 'WPROWADZONE'
        
        url = reverse('admin:enter_local_votes', args=[obj.id])
        return format_html('<a href="{}">WPROWADŹ</a>', url)
    
    def changelist_view(self, request, extra_context = None):
        extra_context = extra_context or {}
        
        extra_context['title'] = 'Wprowadzanie głosów stacjonarnych'
        
        return super().changelist_view(request, extra_context)
    
    def get_urls(self):
        urls = super().get_urls()
        custom_urls = [
            path('enter-local-votes/<int:election_id>/', self.admin_site.admin_view(self.local_votes_view), name='enter_local_votes'),
        ]
        return custom_urls + urls
    
    def local_votes_view(self, request, election_id):
        election = get_object_or_404(Election, pk=election_id)
        options_queryset = election.option_set.all()
        expected_votes_count = Participation.objects.filter(election=election, is_remote=False).count()
        
        if not election.is_hybrid or election.is_active:
            messages.error(request, 'Głosy stacjonarne można wprowadzić tylko dla zakończonych wyborów hybrydowych')
            return HttpResponseRedirect(reverse('admin:hybrid_enterhybridvoteselection_changelist'))
        
        if election.local_votes_entered:
            messages.error(request, 'Głosy stacjonarne zostały już wprowadzone dla tego głosowania')
            return HttpResponseRedirect(reverse('admin:hybrid_enterhybridvoteselection_changelist'))


        if request.POST.get('post') == 'yes':
            form = LocalVotesForm(request.POST, options_queryset=options_queryset, expected_votes_count=expected_votes_count)
            
            if form.is_valid():
                for option in options_queryset:
                    field_name = f'option_{option.id}'
                    votes = form.cleaned_data.get(field_name)
                    
                    option.votes += votes
                    option.save()
                    
                election.local_votes_entered = True
                election.save()
                
                messages.success(request, 'Pomyślnie wprowadzono głosy stacjonarne')
                return HttpResponseRedirect(reverse('admin:hybrid_enterhybridvoteselection_changelist'))
            
        else:
            form = LocalVotesForm(options_queryset=options_queryset, expected_votes_count=expected_votes_count)
        
        context = admin.site.each_context(request)
        context.update({
            'action_checkbox_name': admin.helpers.ACTION_CHECKBOX_NAME,
            'title' : 'Wprowadzenie głosów stacjonarnych',
            'election' : election,
            'form' : form
        })
        
        return render(request, 'admin/enter_local_votes.html', context)
    
    def has_add_permission(self, request):
        return False
    
    def has_change_permission(self, request, obj = None):
        return False
    
    def has_delete_permission(self, request, obj = None):
        return False

admin.site.register(HybridElectionVoter, HybridElectionVoterAdmin)
admin.site.register(EnterHybridVotesElection, EnterHybridVotesElectionAdmin)
 No newline at end of file

hybrid/forms.py

0 → 100644
+29 −0
Changes for hybrid/forms.py: 29 added lines, 0 removed lines.
Original line number Diff line number Diff line
from django import forms
from django.core.exceptions import ValidationError

class LocalVotesForm(forms.Form):
    def __init__(self, *args, **kwargs):
        self.options_queryset = kwargs.pop('options_queryset', [])
        self.expected_votes_count = kwargs.pop('expected_votes_count', 0)
        super().__init__(*args, **kwargs)
        
        for option in self.options_queryset:
            field_name = f'option_{option.id}'
            self.fields[field_name] = forms.IntegerField(label=option.name, initial=0, min_value=0, required=True, widget=forms.NumberInput(attrs={'class': 'form-control'}))
            
    def clean(self):
        cleaned_data = super().clean()
        
        entered_votes_count = 0
        
        for option in self.options_queryset:
            field_name = f'option_{option.id}'
            value = cleaned_data.get(field_name)
            
            if value is not None:
                entered_votes_count += value
                
        if entered_votes_count != self.expected_votes_count:
            raise ValidationError(f'Otrzymano {entered_votes_count} głosów, a oczekiwano {self.expected_votes_count}')
        
        return cleaned_data
 No newline at end of file
+7 −0
Changes for hybrid/models.py: 7 added lines, 0 removed lines.
Original line number Diff line number Diff line
from django.db import models

from voters.models import Voter
from elections.models import Election

class HybridElectionVoter(Voter):
    class Meta:
        proxy = True
        verbose_name = 'Wydaj karty'
        verbose_name_plural = 'Wydawanie kart'
        
class EnterHybridVotesElection(Election):
    class Meta:
        proxy = True
        verbose_name = 'Wprowadź głosy stacjonarne'
        verbose_name_plural = 'Wprowadź głosy stacjonarne'
 No newline at end of file
+23 −0
Changes for hybrid/templates/admin/enter_local_votes.html: 23 added lines, 0 removed lines.
Original line number Diff line number Diff line
{% extends 'admin/base_site.html' %}
{% load admin_urls %}

{% block title %} {{ title }} | {{ site_title }}{% endblock %}

{% block content %}
    <div class="delete-confirmation delete-selected-confirmation">

    <p>Czy na pewno chcesz wprowadzić głosy stacjonarne w wyborach <b>{{ election.name }}</b>? Tą akcję można wykonać tylko raz i nie da się jej cofnąć.</p>

    <form method="post">
        {% csrf_token %}
        <fieldset class="module aligned">
            {{ form.as_p }}
        </fieldset>
        
        <div class="submit-row">
            <input type="hidden" name="post" value="yes">
            <input type="submit" value="Zatwierdź głosy stacjonarne">
        </div>
    </form>
    </div>
{% endblock %}
 No newline at end of file
+1 −0
Changes for pyproject.toml: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ dependencies = [
    "django>=6.0.3",
    "django-environ>=0.13.0",
    "django-rq>=4.0.1",
    "django-smartbase-admin",
    "django-tasks-rq>=0.12.0",
    "honcho>=2.0.0",
    "redis>=7.3.0",