From ac90cc59f42bc933f61f2dc34166d1fb506541d1 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sun, 25 Jan 2026 21:46:44 +0000 Subject: [PATCH] Autosave: 20260125-214643 --- ERD.md | 13 +++- core/__pycache__/admin.cpython-311.pyc | Bin 72102 -> 74954 bytes core/__pycache__/forms.cpython-311.pyc | Bin 15106 -> 15471 bytes core/__pycache__/models.cpython-311.pyc | Bin 23597 -> 25879 bytes core/admin.py | 72 ++++++++++++++---- core/forms.py | 13 ++-- ...rticipation_participation_type_and_more.py | 18 +++++ ...icipation_participation_status_and_more.py | 37 +++++++++ ...tion_participation_status_link_and_more.py | 23 ++++++ ...nt_end_time_event_name_event_start_time.py | 28 +++++++ ...articipation_type_and_more.cpython-311.pyc | Bin 0 -> 850 bytes ...ticipation_status_and_more.cpython-311.pyc | Bin 0 -> 2052 bytes ...rticipationstatus_and_more.cpython-311.pyc | Bin 0 -> 1850 bytes ...ation_status_link_and_more.cpython-311.pyc | Bin 0 -> 1012 bytes ...vent_name_event_start_time.cpython-311.pyc | Bin 0 -> 1166 bytes core/models.py | 49 +++++++++--- core/templates/admin/event_change_list.html | 31 ++++++++ .../participationstatus_change_list.html | 31 ++++++++ core/templates/admin/voter_change_list.html | 31 ++++++++ core/templates/base.html | 30 ++++++++ core/templates/core/voter_detail.html | 18 ++--- 21 files changed, 355 insertions(+), 39 deletions(-) create mode 100644 core/migrations/0015_remove_eventparticipation_participation_type_and_more.py create mode 100644 core/migrations/0016_alter_eventparticipation_participation_status_and_more.py create mode 100644 core/migrations/0017_remove_eventparticipation_participation_status_link_and_more.py create mode 100644 core/migrations/0018_event_end_time_event_name_event_start_time.py create mode 100644 core/migrations/__pycache__/0015_remove_eventparticipation_participation_type_and_more.cpython-311.pyc create mode 100644 core/migrations/__pycache__/0016_alter_eventparticipation_participation_status_and_more.cpython-311.pyc create mode 100644 core/migrations/__pycache__/0016_participationstatus_and_more.cpython-311.pyc create mode 100644 core/migrations/__pycache__/0017_remove_eventparticipation_participation_status_link_and_more.cpython-311.pyc create mode 100644 core/migrations/__pycache__/0018_event_end_time_event_name_event_start_time.cpython-311.pyc create mode 100644 core/templates/admin/participationstatus_change_list.html diff --git a/ERD.md b/ERD.md index a5aac2c..68315ba 100644 --- a/ERD.md +++ b/ERD.md @@ -7,6 +7,7 @@ erDiagram Tenant ||--o{ DonationMethod : defines Tenant ||--o{ ElectionType : defines Tenant ||--o{ EventType : defines + Tenant ||--o{ ParticipationStatus : defines Tenant ||--o{ Voter : belongs_to Tenant ||--o{ Event : organizes @@ -20,6 +21,7 @@ erDiagram Event ||--o{ EventParticipation : includes EventType ||--o{ Event : categorizes + ParticipationStatus ||--o{ EventParticipation : defines_status InteractionType ||--o{ Interaction : categorizes DonationMethod ||--o{ Donation : categorizes @@ -76,6 +78,13 @@ erDiagram boolean is_active } + ParticipationStatus { + int id PK + int tenant_id FK + string name + boolean is_active + } + Voter { int id PK int tenant_id FK @@ -121,7 +130,7 @@ erDiagram int id PK int event_id FK int voter_id FK - string participation_type + int participation_status_id FK } Donation { @@ -147,4 +156,4 @@ erDiagram int election_type_id FK string likelihood } -``` \ No newline at end of file +``` diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index cf83c170db96a108b806e0ba8dfb57fab8bf0088..5ea9b26d96fb11ef1894249c2b22e12fb29b8bcd 100644 GIT binary patch delta 13753 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 delta 11412 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 diff --git a/core/__pycache__/forms.cpython-311.pyc b/core/__pycache__/forms.cpython-311.pyc index aaf24e429ab060101c6e3236799d7a755ce5327b..73a5120cb5df46ade2b16ffb168642b65b893af5 100644 GIT binary patch delta 4115 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 IN<|C*1^U?%{Qv*} diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index 95094701b6dc517f71b4ec300ec66a5d84408fc0..42a3f85ffedb30e4f60c47d927ae17faf6bff604 100644 GIT binary patch delta 8435 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 Rdzjh7LC-w*wgzqB{{e78NYelS delta 6592 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 literal 0 HcmV?d00001 diff --git a/core/migrations/__pycache__/0016_alter_eventparticipation_participation_status_and_more.cpython-311.pyc b/core/migrations/__pycache__/0016_alter_eventparticipation_participation_status_and_more.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d7b26f4367731ade5faede022831a998ac91c75f GIT binary patch literal 2052 zcmah~y>Ht_6hBfFCCc)L=nqA)t)#Y*M5$pp1!`A8+{Cq$AZ?QvwueF}K+w9gOqn8; zBc;Y#>Y+e8W~+zJZi{Hh(7{9hfQ~f4LAa?vCvObwDO2x`mJ%ffa^$_^yL%tM_uk#{ z_x}C_plx!yVf-8g;6KK68s&LAU8TdX00JnOpeWE$G{tJ97^zA{NdO{v2w>zV03{Tu zbacRB1b~;chpiZe!Uo7iPZ;|oCz3?fC}Z6JlTCrY4+(x{!3gb}WHk9s+M6D!XUn_Yi zQ9HDUZCix>?|B<&4IWaIFKO?}3~?ErTQ&!!R_X&8mCN*OMOPSOx@b0`%QnYnaC=;JGltu*pAaIy^4s$X>{8_CM3ga z??Tz&rif_32Sj|dnv+OUue-KZ!bo=!Bz-k(RCT%RI0zfMX*3Z@HW1#j9mE}A zR<;w!&|%gEh9I2YmK zMCJ){NX)K_~7 z{Z4Ayv$}4w>M#zX8nPg=N(OQ;yH`kJ*>n+p!0LwC@g&O1jvn%)Z-tlWF)K4ker1%G zY2COe!?*O0l)| zr2)sp5-S0_V&xu z)3BiFER>HQhA@lW<1km-!|bBqgx!A5_w)|h?>>PHl&3-v5l7_xZ-WF-vcDw!_+&f% zX*+ejtxmnT=BrbGj2umQ>e8{gkZv&r!wC7?7@ORKKrWi*Pg%l&|h5h7r*n$KL!BY7uQ8POl*j+IX&Z) z&ZIWQK#7hF1Owp4J)u3b;7u+Z^YT6B!~!tKx-&`;(@E-+Xgqhi{3!a W3UUBGBrg*F(9CPLaCX5e$M8Rze?7ne literal 0 HcmV?d00001 diff --git a/core/migrations/__pycache__/0016_participationstatus_and_more.cpython-311.pyc b/core/migrations/__pycache__/0016_participationstatus_and_more.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dd88a242658ddefa2222e86c34812ac216be55a1 GIT binary patch literal 1850 zcmah}J#5=X6h8il5@p$zY=mS!WuGk@X)nDM;hQD+*F`bHX1fiAXD#1ONn3uJ(7?2?%uth@4b7! z3=YNt9si<+_NNHIKaA;)$i?Jrg-(6~5I{}`C64}iov#Tcp(d6@4)EX!fWi*|ib$w- z&wxV#fFt^aqZEPMCdfzLG4@5CC-ItA!K$s9hDD^B36XABR}))(f(a( zNvsa{&X2+Ie%loH|FfR#ozAqc^=ofu`}qoAO2O+iR}(~j-pvtBm{>M3A`kE1pL?KS zR5Ke$K@DWsbrsuMS*r)RRQfr)Sx1U$K&8gcj;wzyx@oJnV-a41TWf@Wx{?=3LUn9Y zDPyGC2$F$1)@mwlDz8wJ$QHtys%tGo5)Fj6O$#Z8T0=x+^c|$}KjEzM#bJG zvSul2+146}ZbTv4Q61eTl8p@2u*rD8qgLPyvRVTy%GppTFA&)@6k3|dre-nHnO~t< z-Zop~eev851434w$79qT%rK|8jeP8`Qr8`<>SWk4wAT(&Y_o#wU4-*OAWozm4e8J# zQL`Rijr3)V$>>$Sx2^@A_icqy(J(~A(RG|*US*kA0!4~lxgeI%awM?)BA+HPC0JGz z5?5&Apra!?PbkW3N7WhHjDx6-42X=fhAhl(IT=_E^7fqR#q7qB#AB_pL^Ha^Vj}YL zu8PBH;<0J!NHsz(zD6O}D#kOKW(ihRqhb;sZj)F5JZ%spy1cZxytJ}P;!C=XE|f&q zH(qY7E^m>zSw|P0pi{%W;@T1b+H+~$*w|}~?q&0DH{ERUBwO^dMK}4dle*#N z<_>ne+}!b$n_E1|Eqb{{H~FZO%DNLX2lL*<%-hEAO>g0ex3KOleCt-e_W@YtH+cHH zvB{qX^gN(+CAG!-a%6PK9|F^lxX#qPJGtOTgs~wXFp^5h@l!y_IV1jcAm>;NH#?b6 zJE>1P>B;@OUV8G^(c|$yvR?72SKRQ5C0A*>>DEcQ<)vGGRAd?`IcLPbIg*z4zGe^p zybE1kBH1vHV%6u+|_$8o4ss#YZfUlI~TmEy3#0AfNQA*c{+9ypxbBe?Y!XFG*00|O&l z|AQh_{+JFOBCkwru9B$}@6K^c)eOA5d-r>~_wIi0z5B7UViT12AIAPbBjmR?wkM!U?AVaVhRvpoO}thlXoVqLJr>>t6{sK;Nlj$bnACA+Ac?2B&XHxA8}s+g+`& zLw_W^%#WkAFvFNbkPa8VYBLwc>>YxA0_t5?<8(w_T_a$ezr;1J|1u7c{UNSOlt+CB z^5qTmF)wl&X>OA@k(E`nUe#=nnlX$86p#A-`wy5GWFQ!fA<7a@Wd6`k6lr$RN;5CZ zQ|3jSg)(^UazwGdEJRg8X3ruogu+m|v&@qPeze=wMH>?=tT^CRgcZS_Lfe>z#S~<$ zuo)8Jc>sv7F!m|;0(rHxI3y5ph=x9-LN=&qzkx6w!!sWOE)D5f8Frk&qDw!?OqTXE zb3Vo)IQbxtvfP2sFwC=9ID4_!O%rbjj;x+@-dzXl_>c+p!haW1=6Y7mUh+lARw~s* zpnl4P)T1;>>oqNPZQY!_EN#-d`OQAIZcI0~rdRKl4ZUTb5L9!iO6%X_jsA3Ft85z5 z1JzurvTd)KlNWM`YxS#Lv*_?0FB-)?KIm27wTE2;`GE_wIx1RcE~>7=sKdpkMC!H< zqEqW})to2dI+_$$IzUzGlv2!w-aaC?syQY1j+V{RT%~47F01eM@#>uuc`#pcsyO@w D<-;6F literal 0 HcmV?d00001 diff --git a/core/migrations/__pycache__/0018_event_end_time_event_name_event_start_time.cpython-311.pyc b/core/migrations/__pycache__/0018_event_end_time_event_name_event_start_time.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9aea5af4db9d61f9cff3dd85498899dba0e78ae8 GIT binary patch literal 1166 zcmb7C&rj4q6rO3jr7d8vA#wmTL1XNN;z>!!CPbr&Q7#e=y-d10&!Sf?%Gje`e| z-1rYr0|$?u{2L(I1L;*S+)9=c7kx8J*&v35Y3G~wX6AkG%{TL9eB46N%48$xD+v7( zPStAXMt=#69YhhuA&RhvBgIoNQqW68l~0JO47b%PXcw%#3(r%j_7*v{W3lWgg%t%Y z?q@*~r-dFRl!a-tiWH+P2FCtxfE~n;hbi(Did)!I6~wf5RTQMAVn%O|h(OV(Mz#Ig zE*xVI`k?LWmkYYWF(NsPYCmuo`{oTftee--QazK7f;3}=`KHnY1k#!bXT|cu!s91| zvnbhMgl(`m>-szknn71;M=pD5=4W|I!XWMtKc*xS6g3%E7z`$|AY!XPUTcJY+$pp; z4?{GM^#xkWZWHL>-<|>pZ{la{0ZC0%y@ zTE3w^>_cY_cRh)in>X?}%U!m~nt7IR_d~)vY1eNuSLo*sUzrO^J{?F%Dk;ugS)5df z439M5{m6AlBtaPIPk^n9uhfybhD%kM)VE%j7BXi(TRmg?XzK3K?dcm+A;Km|Ah+g5Ml!HHNn{m-h*`xn`fEC>Jq literal 0 HcmV?d00001 diff --git a/core/models.py b/core/models.py index eafb0d4..5c0a55b 100644 --- a/core/models.py +++ b/core/models.py @@ -6,9 +6,21 @@ import urllib.request import logging from decimal import Decimal from django.conf import settings +import re logger = logging.getLogger(__name__) +def format_phone_number(phone): + """Formats a phone number to (xxx) xxx-xxxx if it has 10 digits or 11 starting with 1.""" + if not phone: + return phone + digits = re.sub(r'\D', '', str(phone)) + if len(digits) == 10: + return f"({digits[:3]}) {digits[3:6]}-{digits[6:]}" + elif len(digits) == 11 and digits.startswith('1'): + return f"({digits[1:4]}) {digits[4:7]}-{digits[7:]}" + return phone + class Tenant(models.Model): name = models.CharField(max_length=100) created_at = models.DateTimeField(auto_now_add=True) @@ -76,6 +88,18 @@ class EventType(models.Model): def __str__(self): return self.name +class ParticipationStatus(models.Model): + tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, related_name='participation_statuses') + name = models.CharField(max_length=100) + is_active = models.BooleanField(default=True) + + class Meta: + unique_together = ('tenant', 'name') + verbose_name_plural = 'Participation Statuses' + + def __str__(self): + return self.name + class Interest(models.Model): tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, related_name='interests') name = models.CharField(max_length=100) @@ -189,6 +213,9 @@ class Voter(models.Model): return False, err def save(self, *args, **kwargs): + # Auto-format phone number + self.phone = format_phone_number(self.phone) + # Ensure longitude is truncated to 12 characters before saving if self.longitude: self.longitude = Decimal(str(self.longitude)[:12]) @@ -243,11 +270,16 @@ class VotingRecord(models.Model): class Event(models.Model): tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, related_name='events') + name = models.CharField(max_length=255, blank=True) date = models.DateField() + start_time = models.TimeField(null=True, blank=True) + end_time = models.TimeField(null=True, blank=True) event_type = models.ForeignKey(EventType, on_delete=models.PROTECT, null=True) description = models.TextField(blank=True) def __str__(self): + if self.name: + return f"{self.name} ({self.date})" return f"{self.event_type} on {self.date}" class Volunteer(models.Model): @@ -259,6 +291,11 @@ class Volunteer(models.Model): interests = models.ManyToManyField(Interest, blank=True, related_name='volunteers') assigned_events = models.ManyToManyField(Event, through='VolunteerEvent', related_name='assigned_volunteers') + def save(self, *args, **kwargs): + # Auto-format phone number + self.phone = format_phone_number(self.phone) + super().save(*args, **kwargs) + def __str__(self): return self.name @@ -271,18 +308,12 @@ class VolunteerEvent(models.Model): return f"{self.volunteer} at {self.event} as {self.role}" 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.CharField(max_length=50, choices=PARTICIPATION_TYPE_CHOICES, default='invited') + participation_status = models.ForeignKey(ParticipationStatus, on_delete=models.PROTECT, null=True) def __str__(self): - return f"{self.voter} at {self.event} ({self.get_participation_type_display()})" + return f"{self.voter} at {self.event} ({self.participation_status})" class Donation(models.Model): voter = models.ForeignKey(Voter, on_delete=models.CASCADE, related_name='donations') @@ -328,4 +359,4 @@ class CampaignSettings(models.Model): verbose_name_plural = 'Campaign Settings' def __str__(self): - return f'Settings for {self.tenant.name}' + return f'Settings for {self.tenant.name}' \ No newline at end of file diff --git a/core/templates/admin/event_change_list.html b/core/templates/admin/event_change_list.html index df48ce9..b0d7076 100644 --- a/core/templates/admin/event_change_list.html +++ b/core/templates/admin/event_change_list.html @@ -1,7 +1,38 @@ {% extends "admin/change_list.html" %} +{% load i18n admin_urls static admin_list %} + {% block object-tools-items %}
  • Import Events
  • {{ block.super }} {% endblock %} + +{% block search %} + {{ block.super }} +
    + + +
    + + +{% endblock %} \ No newline at end of file diff --git a/core/templates/admin/participationstatus_change_list.html b/core/templates/admin/participationstatus_change_list.html new file mode 100644 index 0000000..4d3b166 --- /dev/null +++ b/core/templates/admin/participationstatus_change_list.html @@ -0,0 +1,31 @@ +{% extends "admin/change_list.html" %} +{% load i18n admin_urls static admin_list %} + +{% block search %} + {{ block.super }} +
    + + +
    + + +{% endblock %} \ No newline at end of file diff --git a/core/templates/admin/voter_change_list.html b/core/templates/admin/voter_change_list.html index eb36f95..c2393d1 100644 --- a/core/templates/admin/voter_change_list.html +++ b/core/templates/admin/voter_change_list.html @@ -1,7 +1,38 @@ {% extends "admin/change_list.html" %} +{% load i18n admin_urls static admin_list %} + {% block object-tools-items %}
  • Import Voters
  • {{ block.super }} {% endblock %} + +{% block search %} + {{ block.super }} +
    + + +
    + + +{% endblock %} \ No newline at end of file diff --git a/core/templates/base.html b/core/templates/base.html index c922003..d42c9a2 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -74,5 +74,35 @@ + + \ No newline at end of file diff --git a/core/templates/core/voter_detail.html b/core/templates/core/voter_detail.html index 2dab959..0e1f86f 100644 --- a/core/templates/core/voter_detail.html +++ b/core/templates/core/voter_detail.html @@ -327,7 +327,7 @@ Date Event Type - Type + Status Description Actions @@ -338,12 +338,12 @@ {{ participation.event.date|date:"M d, Y" }} {{ participation.event.event_type.name }} - {% if participation.participation_type == 'attended' %} + {% if participation.participation_status.name|lower == 'attended' %} Attended - {% elif participation.participation_type == 'invited_not_attended' %} + {% elif participation.participation_status.name|lower == "invited but didn't attend" or participation.participation_status.name|lower == "invited but didn't attend" %} Did Not Attend {% else %} - Invited + {{ participation.participation_status.name }} {% endif %} {{ participation.event.description|truncatechars:60 }} @@ -799,7 +799,7 @@
    - {{ event_participation_form.participation_type }} + {{ event_participation_form.participation_status }}
    - + {% for status in event_participation_form.fields.participation_status.queryset %} + {% endfor %}
    @@ -998,4 +998,4 @@ } }); -{% endblock %} +{% endblock %} \ No newline at end of file