diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index 9eeed8d..c60c979 100644 Binary files a/core/__pycache__/admin.cpython-311.pyc and b/core/__pycache__/admin.cpython-311.pyc differ diff --git a/core/__pycache__/forms.cpython-311.pyc b/core/__pycache__/forms.cpython-311.pyc index dc6edf3..1bb7bb9 100644 Binary files a/core/__pycache__/forms.cpython-311.pyc and b/core/__pycache__/forms.cpython-311.pyc differ diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index a033569..2c3fe0d 100644 Binary files a/core/__pycache__/models.cpython-311.pyc and b/core/__pycache__/models.cpython-311.pyc differ diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index d1c2c24..a3e9c96 100644 Binary files a/core/__pycache__/urls.cpython-311.pyc and b/core/__pycache__/urls.cpython-311.pyc differ diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 2b1d115..da2d528 100644 Binary files a/core/__pycache__/views.cpython-311.pyc and b/core/__pycache__/views.cpython-311.pyc differ diff --git a/core/admin.py b/core/admin.py index 5395bfb..ddcba09 100644 --- a/core/admin.py +++ b/core/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin from .models import ( - Tenant, TenantUserRole, InteractionType, DonationMethod, ElectionType, Voter, + Tenant, TenantUserRole, InteractionType, DonationMethod, ElectionType, EventType, Voter, VotingRecord, Event, EventParticipation, Donation, Interaction, VoterLikelihood ) @@ -22,18 +22,27 @@ class TenantUserRoleAdmin(admin.ModelAdmin): @admin.register(InteractionType) class InteractionTypeAdmin(admin.ModelAdmin): - list_display = ('name', 'tenant') - list_filter = ('tenant',) + list_display = ('name', 'tenant', 'is_active') + list_filter = ('tenant', 'is_active') + search_fields = ('name',) @admin.register(DonationMethod) class DonationMethodAdmin(admin.ModelAdmin): - list_display = ('name', 'tenant') - list_filter = ('tenant',) + list_display = ('name', 'tenant', 'is_active') + list_filter = ('tenant', 'is_active') + search_fields = ('name',) @admin.register(ElectionType) class ElectionTypeAdmin(admin.ModelAdmin): - list_display = ('name', 'tenant') - list_filter = ('tenant',) + list_display = ('name', 'tenant', 'is_active') + list_filter = ('tenant', 'is_active') + search_fields = ('name',) + +@admin.register(EventType) +class EventTypeAdmin(admin.ModelAdmin): + list_display = ('name', 'tenant', 'is_active') + list_filter = ('tenant', 'is_active') + search_fields = ('name',) class VotingRecordInline(admin.TabularInline): model = VotingRecord @@ -61,9 +70,9 @@ class VoterAdmin(admin.ModelAdmin): @admin.register(Event) class EventAdmin(admin.ModelAdmin): list_display = ('event_type', 'date', 'tenant') - list_filter = ('tenant', 'date') + list_filter = ('tenant', 'date', 'event_type') @admin.register(EventParticipation) class EventParticipationAdmin(admin.ModelAdmin): list_display = ('voter', 'event') - list_filter = ('event__tenant', 'event') \ No newline at end of file + list_filter = ('event__tenant', 'event') diff --git a/core/forms.py b/core/forms.py index 8235a81..72519d6 100644 --- a/core/forms.py +++ b/core/forms.py @@ -1,5 +1,5 @@ from django import forms -from .models import Voter, Interaction, Donation, VoterLikelihood, InteractionType, DonationMethod, ElectionType, Event, EventParticipation +from .models import Voter, Interaction, Donation, VoterLikelihood, InteractionType, DonationMethod, ElectionType, Event, EventParticipation, EventType class VoterForm(forms.ModelForm): class Meta: @@ -33,7 +33,7 @@ class InteractionForm(forms.ModelForm): def __init__(self, *args, tenant=None, **kwargs): super().__init__(*args, **kwargs) if tenant: - self.fields['type'].queryset = InteractionType.objects.filter(tenant=tenant) + self.fields['type'].queryset = InteractionType.objects.filter(tenant=tenant, is_active=True) for field in self.fields.values(): field.widget.attrs.update({'class': 'form-control'}) self.fields['type'].widget.attrs.update({'class': 'form-select'}) @@ -49,7 +49,7 @@ class DonationForm(forms.ModelForm): def __init__(self, *args, tenant=None, **kwargs): super().__init__(*args, **kwargs) if tenant: - self.fields['method'].queryset = DonationMethod.objects.filter(tenant=tenant) + self.fields['method'].queryset = DonationMethod.objects.filter(tenant=tenant, is_active=True) for field in self.fields.values(): field.widget.attrs.update({'class': 'form-control'}) self.fields['method'].widget.attrs.update({'class': 'form-select'}) @@ -62,7 +62,7 @@ class VoterLikelihoodForm(forms.ModelForm): def __init__(self, *args, tenant=None, **kwargs): super().__init__(*args, **kwargs) if tenant: - self.fields['election_type'].queryset = ElectionType.objects.filter(tenant=tenant) + self.fields['election_type'].queryset = ElectionType.objects.filter(tenant=tenant, is_active=True) for field in self.fields.values(): field.widget.attrs.update({'class': 'form-control'}) self.fields['election_type'].widget.attrs.update({'class': 'form-select'}) @@ -79,4 +79,33 @@ class EventParticipationForm(forms.ModelForm): self.fields['event'].queryset = Event.objects.filter(tenant=tenant) for field in self.fields.values(): field.widget.attrs.update({'class': 'form-control'}) - self.fields['event'].widget.attrs.update({'class': 'form-select'}) \ No newline at end of file + self.fields['event'].widget.attrs.update({'class': 'form-select'}) + +class EventForm(forms.ModelForm): + class Meta: + model = Event + fields = ['date', 'event_type', 'description'] + widgets = { + 'date': forms.DateInput(attrs={'type': 'date'}), + 'description': forms.Textarea(attrs={'rows': 2}), + } + + def __init__(self, *args, tenant=None, **kwargs): + super().__init__(*args, **kwargs) + if tenant: + self.fields['event_type'].queryset = EventType.objects.filter(tenant=tenant, is_active=True) + for field in self.fields.values(): + field.widget.attrs.update({'class': 'form-control'}) + self.fields['event_type'].widget.attrs.update({'class': 'form-select'}) + +class EventTypeForm(forms.ModelForm): + class Meta: + model = EventType + fields = ['name', 'is_active'] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + for field in self.fields.values(): + if not isinstance(field.widget, forms.CheckboxInput): + field.widget.attrs.update({'class': 'form-control'}) + self.fields['is_active'].widget.attrs.update({'class': 'form-check-input'}) \ No newline at end of file diff --git a/core/migrations/0004_remove_voter_geocode_donationmethod_is_active_and_more.py b/core/migrations/0004_remove_voter_geocode_donationmethod_is_active_and_more.py new file mode 100644 index 0000000..e75116c --- /dev/null +++ b/core/migrations/0004_remove_voter_geocode_donationmethod_is_active_and_more.py @@ -0,0 +1,50 @@ +# Generated by Django 5.2.7 on 2026-01-24 14:50 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0003_tenantuserrole'), + ] + + operations = [ + migrations.RemoveField( + model_name='voter', + name='geocode', + ), + migrations.AddField( + model_name='donationmethod', + name='is_active', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='electiontype', + name='is_active', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='interactiontype', + name='is_active', + field=models.BooleanField(default=True), + ), + migrations.CreateModel( + name='EventType', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100)), + ('is_active', models.BooleanField(default=True)), + ('tenant', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='event_types', to='core.tenant')), + ], + options={ + 'unique_together': {('tenant', 'name')}, + }, + ), + migrations.AlterField( + model_name='event', + name='event_type', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='core.eventtype'), + ), + ] diff --git a/core/migrations/__pycache__/0004_remove_voter_geocode_donationmethod_is_active_and_more.cpython-311.pyc b/core/migrations/__pycache__/0004_remove_voter_geocode_donationmethod_is_active_and_more.cpython-311.pyc new file mode 100644 index 0000000..62fe111 Binary files /dev/null and b/core/migrations/__pycache__/0004_remove_voter_geocode_donationmethod_is_active_and_more.cpython-311.pyc differ diff --git a/core/models.py b/core/models.py index c32522a..92d0a64 100644 --- a/core/models.py +++ b/core/models.py @@ -35,6 +35,7 @@ class TenantUserRole(models.Model): class InteractionType(models.Model): tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, related_name='interaction_types') name = models.CharField(max_length=100) + is_active = models.BooleanField(default=True) class Meta: unique_together = ('tenant', 'name') @@ -45,6 +46,7 @@ class InteractionType(models.Model): class DonationMethod(models.Model): tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, related_name='donation_methods') name = models.CharField(max_length=100) + is_active = models.BooleanField(default=True) class Meta: unique_together = ('tenant', 'name') @@ -55,6 +57,18 @@ class DonationMethod(models.Model): class ElectionType(models.Model): tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, related_name='election_types') name = models.CharField(max_length=100) + is_active = models.BooleanField(default=True) + + class Meta: + unique_together = ('tenant', 'name') + + def __str__(self): + return f"{self.name} ({self.tenant.name})" + +class EventType(models.Model): + tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, related_name='event_types') + name = models.CharField(max_length=100) + is_active = models.BooleanField(default=True) class Meta: unique_together = ('tenant', 'name') @@ -104,7 +118,7 @@ class VotingRecord(models.Model): class Event(models.Model): tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, related_name='events') date = models.DateField() - event_type = models.CharField(max_length=100) + event_type = models.ForeignKey(EventType, on_delete=models.PROTECT, null=True) description = models.TextField(blank=True) def __str__(self): @@ -150,4 +164,4 @@ class VoterLikelihood(models.Model): unique_together = ('voter', 'election_type') def __str__(self): - return f"{self.voter} - {self.election_type}: {self.get_likelihood_display()}" \ No newline at end of file + return f"{self.voter} - {self.election_type}: {self.get_likelihood_display()}" diff --git a/core/templates/base.html b/core/templates/base.html index d40c799..a1fe79a 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -40,6 +40,9 @@
| Name | +Status | +Actions | +
|---|---|---|
| {{ type.name }} | ++ {% if type.is_active %} + Active + {% else %} + Inactive + {% endif %} + | ++ + + | +
| + + No event types defined yet. + | +||