From 14bf8d729528f5dd570643067105734fa9aba68c Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sat, 24 Jan 2026 16:24:42 +0000 Subject: [PATCH] .7 --- ERD.md | 15 ++---- core/__pycache__/admin.cpython-311.pyc | Bin 5682 -> 5343 bytes core/__pycache__/forms.cpython-311.pyc | Bin 10797 -> 10955 bytes core/__pycache__/models.cpython-311.pyc | Bin 13599 -> 13250 bytes core/__pycache__/views.cpython-311.pyc | Bin 21922 -> 22688 bytes core/admin.py | 13 ++--- core/forms.py | 5 +- ...5_eventparticipation_participation_type.py | 18 +++++++ .../0005_participationtype_and_more.py | 31 ------------ ...ipation_participation_type.cpython-311.pyc | Bin 0 -> 1050 bytes core/models.py | 31 +++++------- core/templates/core/voter_detail.html | 47 ++++++++++++++++-- core/views.py | 21 ++++---- 13 files changed, 96 insertions(+), 85 deletions(-) create mode 100644 core/migrations/0005_eventparticipation_participation_type.py delete mode 100644 core/migrations/0005_participationtype_and_more.py create mode 100644 core/migrations/__pycache__/0005_eventparticipation_participation_type.cpython-311.pyc diff --git a/ERD.md b/ERD.md index b1bb0cf..92f991e 100644 --- a/ERD.md +++ b/ERD.md @@ -7,7 +7,6 @@ erDiagram Tenant ||--o{ DonationMethod : defines Tenant ||--o{ ElectionType : defines Tenant ||--o{ EventType : defines - Tenant ||--o{ ParticipationType : defines Tenant ||--o{ Voter : belongs_to Tenant ||--o{ Event : organizes @@ -25,7 +24,6 @@ erDiagram InteractionType ||--o{ Interaction : categorizes DonationMethod ||--o{ Donation : categorizes ElectionType ||--o{ VoterLikelihood : categorizes - ParticipationType ||--o{ EventParticipation : categorizes Tenant { int id PK @@ -78,13 +76,6 @@ erDiagram boolean is_active } - ParticipationType { - int id PK - int tenant_id FK - string name - boolean is_active - } - Voter { int id PK int tenant_id FK @@ -105,6 +96,7 @@ erDiagram VotingRecord { int id PK int voter_id FK + string participation_type date election_date string election_description string primary_party @@ -122,12 +114,13 @@ erDiagram int id PK int event_id FK int voter_id FK - int participation_type_id FK + string participation_type } Donation { int id PK int voter_id FK + string participation_type date date int method_id FK decimal amount @@ -136,6 +129,7 @@ erDiagram Interaction { int id PK int voter_id FK + string participation_type int type_id FK date date string description @@ -145,6 +139,7 @@ erDiagram VoterLikelihood { int id PK int voter_id FK + string participation_type int election_type_id FK string likelihood } diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index b6b7208e6a061c4bafef9cf82d5899078ff9c7c6..66bd230ffc53b4c6b57364ad0c81a08ba6e8cf6d 100644 GIT binary patch delta 1650 zcmc&!%}*0i5Z`S}x3t^umVQyCd^hqT5+DQt5eh`4F`@@Gkr2C*)l$f7A>jlEy%=bIcs3C3Kk;?+I=u;}Y{B( zZuYjC&MAyFKuq>po6(8jh96S1rrE4(#^9PI*ovhx6fRV&+1a^UIdw(ZHW0(Q&==#7 zWNjqZi3CCb-dc3IPF=3oeHy)I5Xy2wJxCx>f8DsEo_k7VY*l;zk=uvS2n}c)=JpkH zV~)g%lF40JT~bC;3u=ZPUqe5pBgBvD^rOyWmjlk(oiJvr^;aCLjNt)TvIVUJXd-mN z6Py0A2g=ib+Jcqo&cpOUG!eRCRMyi6%hNaINM*XKl-@OrCITKtHppSU^zO@n^~Anx zUr*qx9q#a{k-qA2e12@V2h3eHgmYU6~^BFe5 z*Ks2o!`uYIIEQ51RzB@W<4m%41p0b(fOHJh3~k*=Q#Fb)2*dEn(W?#VsMbIft~%>F zunfKXDJ8899!)o0H@YM=^)$XTd&f0TZBw1J{n3Ae z-c+bGQ_U)B1Hbn#^9a1cFianz6t*i{KxJN4}9UB4bOXVXT$eQG~wa>1%^7E8ODMiA}Nyk{;*_G-)))JR%5ksr^$HI*ox~oVpGS?0c{2Y6Kfd>L8?p8 zjc+{U2ly5pdvZsUTYrf(!-Hl|naQQO$s?a~>iaANkOWB$ho_Rp!^Q5q58mg+yZf&E z?_4gU(dR$^^_vpW7yD=l?#*Mg}FcNOk zNV;Rjn42|bnU)o$G_F=1ZQ7O1rK~3 z)3opD@;}D3uF>dBaL;3}8I9BBe-uZOIL63oHt6l}4$Zh8Va)YmTqDNyp&2*qjnB2>=1*9QMJ5xL?K;(;u$GH?nS9Kv zR@IYv|My9qi$}EzmlF@F9v4>Gb86McFAurQ->X$E-0gGkdCivDy$WxSruSa(s;3O6 zKC^`9l$}Fmt-2Cl)QC)G>Bp%aJmTe=uw_C`k<;p@YmQ6>&ywREZpaBm^QrSSuQ<AL$KO(R*%LEPbicIitJYgMc7u2Wyd}HT%&E-3dr;V!D*x}#s za>J{MoqyKE*Y!iI%y&pO-%-)OdH7Nw!4#yZQC}ozhTpU7QgiPtn``djE0zP({)(^D za9c5{joG>p=ZOPmB<&dKj>~ah_n+|UDGYIlk@0$^aUe5g!7Y#5rsW+ou}WN};+UAj zBN0lmKp?Xfr|y}yQ$MU&FJ-RIEm3}MK67}*t}798%u%tdizQ4_9>XtD2p~(1`Wiu7 z<_|OPHa|U^U1{#0O>Cazx0?6y^(SLqf4O)-uUtDuFF8(P6LO~eC5NILl-x4u`3WBv zl;%ZU6p2l|Lr~OZ9u}qvQ~}ERwtiNWj+2q7h)tR%$5m*aITcEAu?4nB1b&G=z%*U; z6@tzP+@J_dZ#5sD&A!*%$Jdt+`w`{OcB~mJKc)XTre3X*E7MNh#L|Ajk1qpoiykL7 z2uk7xnh^=VMIQiZdJ&ay3lfTuKyR`w0rn$GmPQh`vm9Zgj(Y@&`N{pi-jk3A#q~Bp+_F!@KcExB)_6DUHwTdVC7*Fx^LEOk()~$?^ zpw>1WMl#PFK{ZzuqIAUynyD8!OPP-CZ{;bf$)0e^o}4OMRok(tl$-U&;bBd9#kgPH z9+DF>{n8S)S$7Vq;uE?r#>9R45q}0eASe~bqf2HJV>ba?0JTOwL`%I=h!)#`$Xfas zeE?i_l#|YS$5AXkL9uurWq=CAt{qZ!&dI1P(hp%w zW;jlzrib%u9FbA+AnB^;e@2fGe<3IxCk9K8h$~?dV4to?YWy&>3vsua5ApR24@^hU zvCw-e4n!qX0?^qL+T`?M=V@C>rSo0R7jF9J7x4s6e?d?Ze?>E*>2ve}9?{jK>3wMW zs8bV6OT|r@x4*Kg2eq5!T9s1psfba(Osb=CT_os69hSuyS~%p2GywnUA?W`*G=USL zQ2TNotqFkI`qYMkB`R}|t*4EOB`#O!oQf_40{a2{ifooQ<)-T%(@IMdIy|6j=J zEPt-`!qM+r%QxR(;B9*}rRkH+xo-=vlBaB;#TL%>7~4MAdg0Y}YkK1i2HpbR#58>| zw9f=A`BS#qVyj@e4VEYzZMT-*0n2T$+y={9XdkjnoHFWN14{ucQGk+PgQWnL0$A2V z`;eu>mneZE4Si{|1ilo`Lze6*TWPVC!M-F~i@)mjr4ZVOEa_9W)M85mSzbM9&24wH zEQj_1%gN;WDcfkVje#^rPg*NCx@k5;`%G_2s5Cj6YhC+IPhJc#hNC1ml0*ZHk0>_u zo`y8uYhB;zF%A+damwafY#xj6ONQ0g4`0o-rqU1hp-Z*cJRa9pBm4pkP44HFp8P>ZadLo!u5AS42L^Ul zGRe)=vfYfVnLrnXZRVC|Wn#>lET~w?7&rM0kKyD!ifg&jL5>9xp_8}px=h}#^v$1?b(t8mCo8BO<;n%=01;`E->a1~=1xvmFJc25lRNpo kx-4V)=D+H#j3zvcASYudXN1m){|J`*f~-Pj@;1$K06b!YD*ylh delta 470 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

kl3ijnQmu>u~$%%gg3nKU%$*_eIleOu?E_{bJ_W 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 OQ?G^M(BW|xQt)4z$ZlZ( delta 5500 zcmb_gYitzP72ff_?48}UjlJs!1`l8YYw!aHOk-LM#y|?eykDD#8TL-_!p^R_vo_d` zvPnhyh(cO&t42hPM3B-D*{zhW`X>?%>5u+stIBSzDjJDO{fX2D`l}KxRnIxI-kn_! zXXCRvkH({V zQ@lxUjyLNq@fN)`-U{>nE3Wu*Rt>U^)qq^V0w7m18Du*Pf>c-t zcCdPoYuPf8Pp}4%>sTYm^(+E1#-dj?y5gOz34Ux~%^)|j7LZ-66=XMC4zh=}9d*T4 z+(Y2`XQYj8DIlgiJ)Lg&9rK!gu3enaj4WRXzs+TameLYgjg4ltw3^P2CK+!RzxN#Q zcEYqj-{HL~<=WtuF9$IlJ)N0QRIVxM%q2xv)9Sfo`rLrRQ8`x4y{L#D=POXGM&Sox z`i+T1LNg50lU8+&dtfZ)=1<@}?rZw2ryFRaq9{CugSD1zqv3?AkE_XZY2FLN&0@R% zv}Xg{iCk4Q|B?R>ZfUuAOmuj=^Qz zcD)sD6Wdqxi`ka6g-iOGcrSWO+-?2qQ>^AC&-pOu(cf&~$H3tkxU4_OczJ|!i86qr z0|)@$EY`KHA^cp0!C38M(etyoC{kRRz&o^zQ&^DfmB{@TUD2%-$hih%rkqSe{-}vf z*<>bd;0~4-7BgIBY_y<)8vFuiWZ^P?C8X{i@p{W@p{(+W=@n-hzdv&8`0S}Uxqn{n zUy%FfJpG(PFI^!QHO77}{@E0+Iv*C@&22fGFA8)wLl%Pyg^rv9Q-|PblxfqAU$<;U zLzIberb1QhCZ>In<78aF#Brx!kUUr6G;*YkGiKO^9&2wY70%_XS}g|3}*^3c3Iv>*@7d4?UEdP?K18ZbLHR$pO{}4|L=08$(AeJ;syfBh~Ca78$q1wMi5nr{!U&f zr-)TX?Ch5p(Uenv5;rC42kox`@#oHlz%m~N&Z^ZVY_^gQOD$?cfjcbZP3vuOY;;WYMLN596D)RQa|kCC z6dfpXC>-EZZxO3_F@y@;40%rzpKNMtr`{!ulujitXsP5_2Hv|^)qVk&algpv{e3r~ zm-)QU>voDG&lGKW8Sh>}fiHWjW=9;s5)vY9Iao88NNH*snqesZstqfeZTfTCC-Ml$7NV9aH#bK7nq?EymFSmidG`a$(2jfy%xIzyL064fb#F)GUAf>bZ>XQ zb8F9H|KnWZZ$G8jBJa#kcu^|#SrWVJuuka_AnXR8tf10Z#KB3tqIx7(_=Y)`)em`NS(u8;&?MW%#q_^oKR2@$FJhu zw@{Q)d>8)oprA@tBKm;cFBZ{3%M6XHJey1;$LS5TG|Wwq0^+^B5&3(deGe`pNYSO{ zCq6j)_+p+SFW%qru2jbY;6U!xmmj7lQSMcrW zvn#lzf`U9ncwfVx=oOpK$XyJ_x=^6w7Bi!6T-{=GO?h^_iQ1GMXl=RMME&qe`7Id! z2Trx1yN1Qf!=GXo^!!5Cj)ksWbMo-KJiH(e&v}MzuY#pr(BJl~wmHE$MaT(+kid~U z94g;p;lGBamr{g~IHpKzAw?kifgivkSpqnMD&PIRCnHN+AJCyg@0F*=qzHw#{A35s zzO=8w*Nz5gqIKV@inFTYNv;mH6%-W77QAzVh%|2`<<>V6^Fiuf5&Ds*7=yKw^rH&7rSumQs@Vj;)+ zO#vV~aSL15MJMJ`suI~MP^`3AWd=$n8#XlJ+JVNvJNRgf#rqJ8ZgKa(HwvdrKEmw) zM)2um!a=y3Zm@wUo*%vd208w*SSnx?4$c1T5IVW+qySx@1!_r;U0VVygUocn%$QZ+BkO7rdQ)U!>xQToR5Em zc9z(LW}A|>#OQi5TFe{`d2fQskhp#HU(fcMb?m&FK9}h>#xgvcn1DAglGLii7{HiAhQhXLrb`@E|E!RdGah(ayaK(8u&^OYmWE9_YXR#FMg?L&C%DAUVH+6Q?XhK zJgL(Wm0!d=JgiU~&ao-w*tAgt!|^@M@tw!9rgN-R9P^tv&5>Ok1Hlmw%jijJ_f8y484QrsJ#B95HeN1x^X4G$ik Ak^lez diff --git a/core/admin.py b/core/admin.py index 1f6d628..c79005e 100644 --- a/core/admin.py +++ b/core/admin.py @@ -1,8 +1,7 @@ from django.contrib import admin from .models import ( - Tenant, TenantUserRole, InteractionType, DonationMethod, ElectionType, EventType, - ParticipationType, Voter, VotingRecord, Event, EventParticipation, Donation, - Interaction, VoterLikelihood + Tenant, TenantUserRole, InteractionType, DonationMethod, ElectionType, EventType, Voter, + VotingRecord, Event, EventParticipation, Donation, Interaction, VoterLikelihood ) class TenantUserRoleInline(admin.TabularInline): @@ -45,12 +44,6 @@ class EventTypeAdmin(admin.ModelAdmin): list_filter = ('tenant', 'is_active') search_fields = ('name',) -@admin.register(ParticipationType) -class ParticipationTypeAdmin(admin.ModelAdmin): - list_display = ('name', 'tenant', 'is_active') - list_filter = ('tenant', 'is_active') - search_fields = ('name',) - class VotingRecordInline(admin.TabularInline): model = VotingRecord extra = 1 @@ -82,4 +75,4 @@ class EventAdmin(admin.ModelAdmin): @admin.register(EventParticipation) class EventParticipationAdmin(admin.ModelAdmin): list_display = ('voter', 'event', 'participation_type') - list_filter = ('event__tenant', 'event', 'participation_type') \ No newline at end of file + list_filter = ('event__tenant', 'event', 'participation_type') diff --git a/core/forms.py b/core/forms.py index 72519d6..2ec45de 100644 --- a/core/forms.py +++ b/core/forms.py @@ -71,7 +71,7 @@ class VoterLikelihoodForm(forms.ModelForm): class EventParticipationForm(forms.ModelForm): class Meta: model = EventParticipation - fields = ['event'] + fields = ['event', 'participation_type'] def __init__(self, *args, tenant=None, **kwargs): super().__init__(*args, **kwargs) @@ -80,6 +80,7 @@ class EventParticipationForm(forms.ModelForm): for field in self.fields.values(): field.widget.attrs.update({'class': 'form-control'}) self.fields['event'].widget.attrs.update({'class': 'form-select'}) + self.fields['participation_type'].widget.attrs.update({'class': 'form-select'}) class EventForm(forms.ModelForm): class Meta: @@ -108,4 +109,4 @@ class EventTypeForm(forms.ModelForm): 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 + self.fields['is_active'].widget.attrs.update({'class': 'form-check-input'}) diff --git a/core/migrations/0005_eventparticipation_participation_type.py b/core/migrations/0005_eventparticipation_participation_type.py new file mode 100644 index 0000000..e49ff24 --- /dev/null +++ b/core/migrations/0005_eventparticipation_participation_type.py @@ -0,0 +1,18 @@ +# Generated by Django 5.2.7 on 2026-01-24 16:11 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0004_remove_voter_geocode_donationmethod_is_active_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='eventparticipation', + name='participation_type', + field=models.CharField(choices=[('invited', 'Invited'), ('invited_not_attended', "Invited but didn't attend"), ('attended', 'Attended')], default='invited', max_length=50), + ), + ] diff --git a/core/migrations/0005_participationtype_and_more.py b/core/migrations/0005_participationtype_and_more.py deleted file mode 100644 index d89b0b9..0000000 --- a/core/migrations/0005_participationtype_and_more.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 5.2.7 on 2026-01-24 15:43 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0004_remove_voter_geocode_donationmethod_is_active_and_more'), - ] - - operations = [ - migrations.CreateModel( - name='ParticipationType', - 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='participation_types', to='core.tenant')), - ], - options={ - 'unique_together': {('tenant', 'name')}, - }, - ), - migrations.AddField( - model_name='eventparticipation', - name='participation_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='core.participationtype'), - ), - ] diff --git a/core/migrations/__pycache__/0005_eventparticipation_participation_type.cpython-311.pyc b/core/migrations/__pycache__/0005_eventparticipation_participation_type.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..594b2c5955016f4729e28144f50c13b646d972a9 GIT binary patch literal 1050 zcmZuvzi-n(6uz?^CpN7Fp%OwMh$?Pl4k`n!F*|Paq*5wFp@(QL#Z$k9h3p76(HkMeT1qjL4>LB z0~J!5AA^W=aUF*ktAU@WFbD@_a$Y|{h1wXPXVP)iFdl{qA+J6e8RVNA`$R02@Rhf zCm{fj^d5<&sq?VwCne8aIl%EB@Qoc(kR88ic4dUktewRwYvMWvnUYC!O(t*CfgfN~ zPo??y&uP+p?uzL?i|IBm3^o#*&L}|}=?8+%KdZ2r^MV(qF=uZ+D_rJW{N(P|F6^DV zxp(I3UVVP++HQTmVC>c_;~x}8SGzJ}O~1~r8wVvGl~`0Q$30*KM;Z##uG^bW^-3;J z)U0?`?m*9vJ8}WqW!uVTjr3m9X=QGMtmE49sQ34hd7_-2^ff_Ya?a@+xc7tIn7#{p WhT8?3hAnsZ^pyi0IQmbtJoh)vgCrLK literal 0 HcmV?d00001 diff --git a/core/models.py b/core/models.py index cd5acd0..be81b57 100644 --- a/core/models.py +++ b/core/models.py @@ -41,7 +41,7 @@ class InteractionType(models.Model): unique_together = ('tenant', 'name') def __str__(self): - return self.name + return f"{self.name} ({self.tenant.name})" class DonationMethod(models.Model): tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, related_name='donation_methods') @@ -52,7 +52,7 @@ class DonationMethod(models.Model): unique_together = ('tenant', 'name') def __str__(self): - return self.name + return f"{self.name} ({self.tenant.name})" class ElectionType(models.Model): tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, related_name='election_types') @@ -63,7 +63,7 @@ class ElectionType(models.Model): unique_together = ('tenant', 'name') def __str__(self): - return self.name + return f"{self.name} ({self.tenant.name})" class EventType(models.Model): tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, related_name='event_types') @@ -74,18 +74,7 @@ class EventType(models.Model): unique_together = ('tenant', 'name') def __str__(self): - return self.name - -class ParticipationType(models.Model): - tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, related_name='participation_types') - name = models.CharField(max_length=100) - is_active = models.BooleanField(default=True) - - class Meta: - unique_together = ('tenant', 'name') - - def __str__(self): - return self.name + return f"{self.name} ({self.tenant.name})" class Voter(models.Model): SUPPORT_CHOICES = [ @@ -136,12 +125,18 @@ class Event(models.Model): return f"{self.event_type} on {self.date}" class EventParticipation(models.Model): + PARTICIPATION_TYPE_CHOICES = [ + ("invited", "Invited"), + ("invited_not_attended", "Invited but didn't attend"), + ("attended", "Attended"), + ] + event = models.ForeignKey(Event, on_delete=models.CASCADE, related_name='participations') voter = models.ForeignKey(Voter, on_delete=models.CASCADE, related_name='event_participations') - participation_type = models.ForeignKey(ParticipationType, on_delete=models.SET_NULL, null=True, blank=True) + participation_type = models.CharField(max_length=50, choices=PARTICIPATION_TYPE_CHOICES, default='invited') def __str__(self): - return f"{self.voter} at {self.event}" + return f"{self.voter} at {self.event} ({self.get_participation_type_display()})" class Donation(models.Model): voter = models.ForeignKey(Voter, on_delete=models.CASCADE, related_name='donations') @@ -176,4 +171,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/core/voter_detail.html b/core/templates/core/voter_detail.html index 6b3b9bc..6432bb7 100644 --- a/core/templates/core/voter_detail.html +++ b/core/templates/core/voter_detail.html @@ -283,6 +283,7 @@ Date Event Type + Type Description Actions @@ -292,6 +293,15 @@ {{ participation.event.date|date:"M d, Y" }} {{ participation.event.event_type.name }} + + {% if participation.participation_type == 'attended' %} + Attended + {% elif participation.participation_type == 'invited_not_attended' %} + Did Not Attend + {% else %} + Invited + {% endif %} + {{ participation.event.description|truncatechars:60 }} @@ -711,7 +725,7 @@ {% csrf_token %}