From aade4cc1312d64c1d0f9aa9a16baa44a6e437897 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sat, 24 Jan 2026 15:09:45 +0000 Subject: [PATCH] .6 --- core/__pycache__/admin.cpython-311.pyc | Bin 4933 -> 5308 bytes core/__pycache__/forms.cpython-311.pyc | Bin 8012 -> 10797 bytes core/__pycache__/models.cpython-311.pyc | Bin 11866 -> 12871 bytes core/__pycache__/urls.cpython-311.pyc | Bin 2307 -> 2790 bytes core/__pycache__/views.cpython-311.pyc | Bin 17942 -> 21922 bytes core/admin.py | 27 ++-- core/forms.py | 39 +++++- ...ocode_donationmethod_is_active_and_more.py | 50 +++++++ ...nmethod_is_active_and_more.cpython-311.pyc | Bin 0 -> 2239 bytes core/models.py | 18 ++- core/templates/base.html | 3 + core/templates/core/event_type_list.html | 127 ++++++++++++++++++ core/templates/core/voter_detail.html | 4 +- core/urls.py | 8 +- core/views.py | 71 +++++++++- 15 files changed, 324 insertions(+), 23 deletions(-) create mode 100644 core/migrations/0004_remove_voter_geocode_donationmethod_is_active_and_more.py create mode 100644 core/migrations/__pycache__/0004_remove_voter_geocode_donationmethod_is_active_and_more.cpython-311.pyc create mode 100644 core/templates/core/event_type_list.html diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index 9eeed8d35f6e7b259bfb8c929633f848cd2b4b39..c60c979f24878ce54f64727205e29570fff4187f 100644 GIT binary patch literal 5308 zcmd5<&u`mC7Uoc-tly4*J9eztalEM7INrwS28-@?QEc37H?dHp=>lbUK``RPVJk}B zA(d@zI`j|7tvT)~3#0#x4d`IZWefDw%ff+k>S^CMG$omm48f<8=BMGzn~(3CdGluc zpJFkm(KYqo(3_^xPk4#1^jYEbe<@A-UUM~<)is}4jA^d!rs}$%vQoZb8NO+me%ea= z6V`;Eu`+(v%KAAg=jW}wU$6>((JJ~StK?5wlT6dK`4b=vpG$DW~k4oh*(lq zvt%`Qfz`6InkTD;3#_gwt3|T9dV$qSLTPr0(k0?pCXVr9u$*Ab4`IAUj4NX^UQaL< zhA@_i@%q?|tM2OOT4n8LtegsyrsMiv<7ceAN>QdC^M=z1WhwgoBH-dtv(Dw@r;U&c zrxtq6#^V?JT$b)N8xG!fdHAg9%EC^a_gb?%&v_$MhUVXz)KeDd$7}38;r2&g-?YzZJf^2%l8`BEaqyK&Qq4* zGRt&z5}cB==QVxWsCx}A4C+#?q-Dmo8;;LyTjp%rZ@R5I$_3m0XUnNaEdmKsn$*ba z(&XQU!a2}RsZRT4bL&~t=Uc5Otwz||;@|RGD{P9be>KH7!M;=DTO^xrsiD5T|3V;| z6iiSdSR`n7@8iN!d*`@NZ13O}OR?#2#n-60rRu4qt{3drofonga7Wah*-t%Q zcLOCtPIzi81926dl*h{`t;CS0La<8EllkM!`|XFvvn%c0eVU4#X8s$Bk&v40jB5)psRlbHfaQ=Z?+#C&;G8xi#w7J`%B87?OQWg zeoFsAN=>bjE3;l;V;w)|2WJEDK7CHC5md!36cZA*PzP9`=QJtd4kT0{fo8HN0rr=a zFcT+$D6=R9;$$Xd+Cgi7zbV3s5p5@bAtz+^ zg(F-$@b((wKD}2`;vW5o9l$39)k;3OWU!xzO~5)ptq~P`YD(20-9$qoJO3GV0GI{n z-@n0dWaqykJAa6McJ1FE9d6${{N$^{(%<{{TlBBd)4kYPDRH2Rj~8bLi=4_y(GaF& zj^oT{hd3P?7#TGlBwg*YyTm9S5>yY&(b5y*9-tEdW0nYwA7{29?oRsw?kLm4^b$H2 z29KeUC|#N=0O+s>ZFEW~Mk4L#a3CJh2dkn=n4Fi-PzQid1Fmnt^;`X}!?apilO^|S zr?J<(U28Td(w>ME)yuRxat6Yr7j*~~I5&z6APd0%_#zKbnYV~i380djN*P#$viR6} z(yBY+Y`xB)E+hCJg*6?Ia=SR$M*GVOdSgMUtzT`cYDZK1$O+OXd&J znffE~CD|dqf(2T*Cn?6*v9@}6{_jLjG5tjQwLwm2r4wxsUVYG6zWoLbZ+op7O~2Bf z`>y;leZ&?zYyp}!peYG2H#*Zd-k{+v;7v-?7rXYkn5A^Yu6NjVu-pYp5?*a|mfi)+ zU9j8*%WBuY%QAVysCE@BWw0axO5OuY87yV6taa_XEPcKt2^4A9mmW*(OZlYBQaEBO z9kw#s7qheY&Us(TUHdLe_J}QY*wRRrmtS<|HqNswckM?`=v?ROt$_(0oOl%s_yYNv znEesPuSgUP@R-IsooibI#&JZLM{K^s=1+8k{ezuo!|~-@XKL+@YJ95@Q%d0&cPk9A z>1-Ral5j>u4T$mW9t}+6SU;T7+c)l%66%_eAW4%(}9{(ryw BDgXcg literal 4933 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 Myya0+kJ<760Gs|s!2kdN delta 1835 zcmc(f&rcgi6vsUdtbeWz#Dv&!Vnb2P(OWOdYkf@}_)HE#=s1jBdy9rL$7-rXL z$R&wViBk{gDW^)!A%`mJk3{k%e?S$bQV)h&Mcs-@J?7N((nHik=Z(QFrscw+d-!VR z`)1zEeD=+JJ@Nfu=nGNwyV%z;Z|78THFVhhr)#yluZg(au5&KE;S-nMXpk#G2$8n1 z$UT91o|+fpo|k#PniuAtpLv0r*TlUb^Tcg0-mHh-cS+%=xB-bcjh6~EZ#^a0^TDTN zxzy~wLxdRX(+GTZ;B(Rp=>}7H35^qQtTS5rvEddOJHqjIFFo&w}v+zS2*Sasz z7trZMc@gCVips&;jOJc!VL!(}Zy-N(20MycI&;i`D&yOH1AW zxpEZ4$Cx+)-LU3pZqd#a7M#X~f^Ar|7NrRs*N)P`L~`>v^exuTNdEfm2{`UJ3Lcmq zKQgn@b;+viYDqx7Nlqi`;`u_S&st8i5KCfGq9!CFv?&5%vGuOgq>kW=e& zs(gN`ET`7w>54oJZQ^p0|MWL7)0<5GNq88|VR$I6R1Y=`OWs-dEOdL4a~1N2Jzvlr zA)7B07wjrHepqChk$m;^JeaSZ9(p|}GGrqM$-A%;P6w-nh*{_eJd8v+&3R7qJdXVj zni#@MM^h-HDEvRAvGp%l=@<)GyV*I-i7j>?l1-(*qMY4OM%R_m@_W-|WpquMsVFlr z)Up@53@(|0pIWxqWjMQU58h7HRlFAm{tcx{VG6ECdUjDDPhd4MP#TY&BG7+GBm(^2 z+6(z3u^S%73G+;&?1V#Sm{+Sej0aHmM~G#(9{+&dBs!M+$S@%m@rSnGfyFE^N0hhV}f5ca+8^(S{YJq&$nUv#u zr=T0=2z!6|Lr3|AAcgh9xm*|HNaiO&zsk6^&7VOOKswdJy2Z!V;LY26ZP%5{B;m2jIT7L~5kvDFPXx zQ#}nm#v*GU2?*+tcnL1(wN>OTBP5XVz_et4CiV15wU6srk&1Te8Nd|OkG%`extiflX%|aFncQOI#v$^UBDe(a$WE4p%km-P1PKUI z@U47VAdZjfYkUUUV4=(o=PQo9TCgbWdI~Ix4lle_(c^_L%n7_-IUOI!_AJ6Twd(T} z{44@gyT;i$_|g@C2Ob$Oz14S#bh8B1g`B>-w=3N8T3EeGqDq1)1b+EvXhkrJlzxx8 z3~#y*mUyy`P04eu=^NduWi7le^=?SLn^G@Kx*G*D=dJz4UBFCKc23~CgRN2rXv<~x z0l3SXojf*g%^ceBj`Ak)#GjCe-~v+mb@)!MhPCn|0*QFD%PQ__)hqC@;(hzaD8uRT zOuATVcw{J}&hjT=(Ic@5xb5jI-8~0%*=|7}_`H?-7H~~@jWX+!rbCGQoED!SAaxeno47DTw;!1mbw( zN?{Ju>@CP zwEDK5xXwT^yi^lC#h=9}>G@^iF(zoqC&MSeQ}b=|I4_fyURJdf;m^XOsbOU#84s%8 zX@L7R*De@X!1n0W*1X3S3; LbK7NWZ5#U=9`oyW delta 1404 zcmb7D?MqWp7~h#~x~qG0y3*-%b4@qgbgdUk3j#$zDBIs8k}E zpeykltz5R7Rusb1v}t08US$bMgS*yj7&EEmW||Ro z;OBBdtx}N_5wiidstVwU%C}m+B^EosnM6={Id+^p65D@%80F%gp(BF zN})q&3AT52HuAopAhOqc4xD*~Tp!jTG(uzE1=7b_7^O4S1b1@HbR<4&4aG_}LaM|F z#buR8h0b7HF5piLJ`C zw9ysliI}%(O=10<)^xjWM(di@y5_Vl*lXTQhFI4|%}FE`FBO+DZMdh}zQa`3`afV9Wpj diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index d1c2c2447e3afeb29b80b7b2e3cf3bc8144432f8..a3e9c96b3ce8cbee3e5f16ec1b1125ad5e4e49a9 100644 GIT binary patch delta 539 zcmZn`dM2u|oR^o20SJ!XEy*r5Rfh!C7Gfh%%Ewoc@xuY z=K3m$+{DbhlGMD!yyR5<)UwpP65W!@g4AODTl`>NJct*clUZC+C4)<8VoHksEj}dW zK!GZ4T&it=_E~{V%}j~4(@#ywEJ3vlBvPeIjCMQyl+>Kml2rX$f=ISQ#QZd+CI_$; z3KoGvw@3;^NP`HO$@|y>xRroRMj$TsWZEprew(qBje(W3!Q}#{@`BJSs#X^qgD$WH zUt|fs!V-Lgg##p^zC!ehrtJlnkP9rK7g<8Du!KS-%yzI|vGBbRl6rw9?IKIs6_zxp lgvAckD^`IQBC;>AQK3@@tFnGc|C7V37<^900C@78L*h diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 2b1d115531610b547c1056ae9fcc5abbba1bd376..da2d5285ca94431e6a4f5a8788395ee36d429268 100644 GIT binary patch delta 6714 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 Y&HRc5t_bxed@O>u*r0U55;O6C0ltvii2wiq delta 4169 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 literal 0 HcmV?d00001 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 @@ +
Admin Panel diff --git a/core/templates/core/event_type_list.html b/core/templates/core/event_type_list.html new file mode 100644 index 0000000..fa9e81b --- /dev/null +++ b/core/templates/core/event_type_list.html @@ -0,0 +1,127 @@ +{% extends 'base.html' %} +{% load static %} + +{% block content %} +
+
+
+ +

Event Types

+
+ +
+ +
+
+ + + + + + + + + + {% for type in event_types %} + + + + + + + + + {% empty %} + + + + {% endfor %} + +
NameStatusActions
{{ type.name }} + {% if type.is_active %} + Active + {% else %} + Inactive + {% endif %} + + +
+ {% csrf_token %} + +
+
+ + No event types defined yet. +
+
+
+
+ + + +{% endblock %} diff --git a/core/templates/core/voter_detail.html b/core/templates/core/voter_detail.html index 25aaebb..6b3b9bc 100644 --- a/core/templates/core/voter_detail.html +++ b/core/templates/core/voter_detail.html @@ -291,7 +291,7 @@ {% for participation in event_participations %} {{ participation.event.date|date:"M d, Y" }} - {{ participation.event.event_type }} + {{ participation.event.event_type.name }} {{ participation.event.description|truncatechars:60 }}
diff --git a/core/urls.py b/core/urls.py index 9712077..e2038a7 100644 --- a/core/urls.py +++ b/core/urls.py @@ -23,4 +23,10 @@ urlpatterns = [ path('voters//event-participation/add/', views.add_event_participation, name='add_event_participation'), path('event-participation//edit/', views.edit_event_participation, name='edit_event_participation'), path('event-participation//delete/', views.delete_event_participation, name='delete_event_participation'), -] + + # Maintenance + path('maintenance/event-types/', views.event_type_list, name='event_type_list'), + path('maintenance/event-types/add/', views.event_type_add, name='event_type_add'), + path('maintenance/event-types//edit/', views.event_type_edit, name='event_type_edit'), + path('maintenance/event-types//delete/', views.event_type_delete, name='event_type_delete'), +] \ No newline at end of file diff --git a/core/views.py b/core/views.py index 90f37ba..eebfdf5 100644 --- a/core/views.py +++ b/core/views.py @@ -1,8 +1,8 @@ from django.shortcuts import render, redirect, get_object_or_404 from django.db.models import Q from django.contrib import messages -from .models import Voter, Tenant, Interaction, Donation, VoterLikelihood, EventParticipation, Event -from .forms import VoterForm, InteractionForm, DonationForm, VoterLikelihoodForm, EventParticipationForm +from .models import Voter, Tenant, Interaction, Donation, VoterLikelihood, EventParticipation, Event, EventType, InteractionType, DonationMethod, ElectionType +from .forms import VoterForm, InteractionForm, DonationForm, VoterLikelihoodForm, EventParticipationForm, EventTypeForm def index(request): """ @@ -47,7 +47,13 @@ def voter_list(request): query = query.strip() search_filter = Q(first_name__icontains=query) | Q(last_name__icontains=query) | Q(voter_id__icontains=query) - if " " in query: + if "," in query: + parts = [p.strip() for p in query.split(",")] + if len(parts) >= 2: + last_part = parts[0] + first_part = parts[1] + search_filter |= Q(last_name__icontains=last_part, first_name__icontains=first_part) + elif " " in query: parts = query.split() if len(parts) >= 2: first_part = parts[0] @@ -267,4 +273,61 @@ def delete_event_participation(request, participation_id): if request.method == 'POST': participation.delete() messages.success(request, "Event participation removed.") - return redirect('voter_detail', voter_id=voter_id) \ No newline at end of file + return redirect('voter_detail', voter_id=voter_id) + +def event_type_list(request): + """ + Maintenance page for Event Types. + """ + selected_tenant_id = request.session.get('tenant_id') + if not selected_tenant_id: + messages.warning(request, "Please select a campaign first.") + return redirect('index') + + tenant = get_object_or_404(Tenant, id=selected_tenant_id) + event_types = EventType.objects.filter(tenant=tenant) + + context = { + 'event_types': event_types, + 'selected_tenant': tenant, + 'form': EventTypeForm(), + } + return render(request, 'core/event_type_list.html', context) + +def event_type_add(request): + selected_tenant_id = request.session.get('tenant_id') + tenant = get_object_or_404(Tenant, id=selected_tenant_id) + + if request.method == 'POST': + form = EventTypeForm(request.POST) + if form.is_valid(): + event_type = form.save(commit=False) + event_type.tenant = tenant + event_type.save() + messages.success(request, "Event type added.") + return redirect('event_type_list') + +def event_type_edit(request, type_id): + selected_tenant_id = request.session.get('tenant_id') + tenant = get_object_or_404(Tenant, id=selected_tenant_id) + event_type = get_object_or_404(EventType, id=type_id, tenant=tenant) + + if request.method == 'POST': + form = EventTypeForm(request.POST, instance=event_type) + if form.is_valid(): + form.save() + messages.success(request, "Event type updated.") + return redirect('event_type_list') + +def event_type_delete(request, type_id): + selected_tenant_id = request.session.get('tenant_id') + tenant = get_object_or_404(Tenant, id=selected_tenant_id) + event_type = get_object_or_404(EventType, id=type_id, tenant=tenant) + + if request.method == 'POST': + try: + event_type.delete() + messages.success(request, "Event type deleted.") + except Exception as e: + messages.error(request, f"Cannot delete event type: {e}") + return redirect('event_type_list')