From e2ad03e4464e145f7f1031386d420af3a0739690 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sat, 24 Jan 2026 15:55:19 +0000 Subject: [PATCH] Autosave: 20260124-155519 --- ERD.md | 151 ++++++++++++++++++ core/__pycache__/admin.cpython-311.pyc | Bin 5308 -> 5682 bytes core/__pycache__/models.cpython-311.pyc | Bin 12871 -> 13599 bytes core/admin.py | 15 +- .../0005_participationtype_and_more.py | 31 ++++ ...participationtype_and_more.cpython-311.pyc | Bin 0 -> 1808 bytes core/models.py | 22 ++- 7 files changed, 210 insertions(+), 9 deletions(-) create mode 100644 ERD.md create mode 100644 core/migrations/0005_participationtype_and_more.py create mode 100644 core/migrations/__pycache__/0005_participationtype_and_more.cpython-311.pyc diff --git a/ERD.md b/ERD.md new file mode 100644 index 0000000..b1bb0cf --- /dev/null +++ b/ERD.md @@ -0,0 +1,151 @@ +# Entity Relationship Diagram + +```mermaid +erDiagram + Tenant ||--o{ TenantUserRole : has + Tenant ||--o{ InteractionType : defines + 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 + + User ||--o{ TenantUserRole : assigned_to + + Voter ||--o{ VotingRecord : has + Voter ||--o{ EventParticipation : participates + Voter ||--o{ Donation : makes + Voter ||--o{ Interaction : receives + Voter ||--o{ VoterLikelihood : has + + Event ||--o{ EventParticipation : includes + EventType ||--o{ Event : categorizes + + InteractionType ||--o{ Interaction : categorizes + DonationMethod ||--o{ Donation : categorizes + ElectionType ||--o{ VoterLikelihood : categorizes + ParticipationType ||--o{ EventParticipation : categorizes + + Tenant { + int id PK + string name + string slug + text description + datetime created_at + } + + User { + int id PK + string username + string email + string first_name + string last_name + } + + TenantUserRole { + int id PK + int user_id FK + int tenant_id FK + string role + } + + InteractionType { + int id PK + int tenant_id FK + string name + boolean is_active + } + + DonationMethod { + int id PK + int tenant_id FK + string name + boolean is_active + } + + ElectionType { + int id PK + int tenant_id FK + string name + boolean is_active + } + + EventType { + int id PK + int tenant_id FK + string name + boolean is_active + } + + ParticipationType { + int id PK + int tenant_id FK + string name + boolean is_active + } + + Voter { + int id PK + int tenant_id FK + string voter_id + string first_name + string last_name + text address + string phone + string email + string district + string precinct + date registration_date + string candidate_support + string yard_sign + datetime created_at + } + + VotingRecord { + int id PK + int voter_id FK + date election_date + string election_description + string primary_party + } + + Event { + int id PK + int tenant_id FK + date date + int event_type_id FK + text description + } + + EventParticipation { + int id PK + int event_id FK + int voter_id FK + int participation_type_id FK + } + + Donation { + int id PK + int voter_id FK + date date + int method_id FK + decimal amount + } + + Interaction { + int id PK + int voter_id FK + int type_id FK + date date + string description + text notes + } + + VoterLikelihood { + int id PK + int voter_id FK + 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 c60c979f24878ce54f64727205e29570fff4187f..b6b7208e6a061c4bafef9cf82d5899078ff9c7c6 100644 GIT binary patch literal 5682 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 delta 3237 zcmcImU2Icj815)B7coo#Gm1NldOHiS4f*vc?N?P|{fI{W8$I$#sr zhy*mwID8uf0Z~abfEVZzyzu9O3r$Q6hDg*C6HU~pi5Ek-FnHtlzNH&mTLu@lJx{;$ zeee5z-}C;RbFTkO+4{c4lB?sN&L3leQTuVLU9f*xy+EHOmv!qT=Xk&VnqH7#rE#gC zLe%(%P&RJL`bj_6$yJz$P!4~as)c2+FvlgVg>^ZR6?gPv%^g9KjBGg<&`blW!ot3g z!d9Ss0m4cI2M1N)AhLycUj~2V^iH$9HFxoHw863wNWB6_q`sDP5Y`}+AdsC}9M!^= z+^a$@ES`TAR++1WM(8v5xh7B0!B(ZwB$J)+o7q)@Lq8ra`7!Xp9Ddzug176+*Yqdn zb*FW*{;Z)}cVSKk+rVepMh+MB38J)NDp8L`+<8mnawEF$^KEhIn|aOrcQSV7`EQ+# zi5o;yGtug}U}g6>9QVMJuuTZ$n#XXI@DE(FR8(g4%@!0ysD$Hr6_9Uz2F9vNge~N! zu6Y&n8&TkKgd7eY)(+bjG{eX9inea!_xEwzQ+&Av^|m8WG-mN(L#hv1H!6D&Qk}Lr zPju}_8t-5|IGhpsUYzTNSMy#XTD_ds&lxCr@(X68w~$ zl~U&a^uYYKeM&fXFa37D?QHaSqYOeTztk}fBlv}71qJY3k)Ptfn|q*mytMeD-h+Al zXEO&6FU?&3&&&vuna(VDiwP|0HA8qH7)%I+aArQM%qeWDtEZQPMN?xMn1|G#ylO zJB1fvi(A?`H}eC9jz>h_!GlsXDUj*7oJA3YVScH*;4gQZIAIWsjT5?5NIVtJQoLTN zzMf6-VkbbZIn+oU?<6jYAF}Nw91Z8%K3#AR;d0ap^$}e>UZb&Z+=ZVvS+J7cF?XUCI zT;u{tI))f;?-|IvUT+spKym$pbD^I60Ul%=VJaD^uqg8|2Q_1uw-GfhjmxNrfZkSt z1Fxx@ZX5hke^|JTe8yi`v_iPz_5I*I~%TC z_DShvS-%I)rghUAZ-0}ciyAMbHf1_8p=T*=Ozla_o!XhvTR^(}zk-Sgr{IUC&$DsV zAr-<~i+jAaxI}@Xw~{`*#a@x9DC}p{1gLr_pC}q+Y(`hVV_F@G$OA!TE&GD23H(w4 zo@jn|xMf0@Bg}-c-SOZ}oWDJ_XiF6%)v=!VlMgKWNPP8l*+nfA84YK}&C`Wj;Cjo^ adZWNwLn@rKohiME^S7rKt#D+?>Hh$yFPv5Y diff --git a/core/admin.py b/core/admin.py index ddcba09..1f6d628 100644 --- a/core/admin.py +++ b/core/admin.py @@ -1,7 +1,8 @@ from django.contrib import admin from .models import ( - Tenant, TenantUserRole, InteractionType, DonationMethod, ElectionType, EventType, Voter, - VotingRecord, Event, EventParticipation, Donation, Interaction, VoterLikelihood + Tenant, TenantUserRole, InteractionType, DonationMethod, ElectionType, EventType, + ParticipationType, Voter, VotingRecord, Event, EventParticipation, Donation, + Interaction, VoterLikelihood ) class TenantUserRoleInline(admin.TabularInline): @@ -44,6 +45,12 @@ 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 @@ -74,5 +81,5 @@ class EventAdmin(admin.ModelAdmin): @admin.register(EventParticipation) class EventParticipationAdmin(admin.ModelAdmin): - list_display = ('voter', 'event') - list_filter = ('event__tenant', 'event') + list_display = ('voter', 'event', 'participation_type') + list_filter = ('event__tenant', 'event', 'participation_type') \ No newline at end of file diff --git a/core/migrations/0005_participationtype_and_more.py b/core/migrations/0005_participationtype_and_more.py new file mode 100644 index 0000000..d89b0b9 --- /dev/null +++ b/core/migrations/0005_participationtype_and_more.py @@ -0,0 +1,31 @@ +# 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_participationtype_and_more.cpython-311.pyc b/core/migrations/__pycache__/0005_participationtype_and_more.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..557418fdac9b9af6f7665e45ad2bc2ba478eb55b GIT binary patch literal 1808 zcmah}&2QsG6dyZ|8z<>U(vLK>DjzL~ELGEr-7N(~=|{Q(x~0%Af*i2i%rtfC*x9iY zwiSmSkl@%G{R;}HIqU(XJ#yf{(Up9N=7hwBy}4>nd*Y4VWQn>GW6zuSX5P&2ea-yT z+Z#vFe*4GKzn2jDn+xq0y=E>~f%y?(garc?1sFv`tVW8Fs#KH&B%*r=N4`T?B9Tga z4?2w?bOt?a#V8iGP%iqEiyJwS#jARmYL0H1Hj}FsCWc+Q)(wW_wQ%VO9Ge8VMG*^S zp%@Vnk)9)A5%U?j($hWwOYlXp-0V38pU$9%ZCAvxKr_~!!AdiJ3J7P=J35I#M`_Ps zshPZ?(;MgnvEzCqQE6L@Dsp>grMJWNwK?2}`Dato}dfO!R|G{kt+S2 z-9vb|8=3q1zvu&<{UgmxcTAe2-FRiOn8I1e)k{pd-_8*vOe$HFu=i$XXK$;NRILV4 z8OMJOicP4l8Tuh%$p)c2mQ7Sss}d%0`V@nEIRR=) zd!!n~EIWHl>EOdc4<@@>-Ef%f5K}W9Hdy000xLWrU}hGy=A*LB0784j2Y0Ks*Bg#!CR@Mr+OkxR3f8ceGyi>r_aTsH{t zNmYGV*9;y$E@4t5CMIS{CpP7`mL*n#MBL}+QhtM2a#=4gL5kM6TTEHm(`d*hmo3X6 zni)#*H3*|#Ha~&9$+)7KWs8Y;hsA$u@%ZatCy zoN|k*Yf?93pJ!|@W4i-RE0uAxxswqun|r+FW*5%03to1?9eB5u8h0n=PIkSCxhGTZ z#NzqHqBpVV4t&^3W!m#%*ek#H+zA0V=^eUh* zlln~bmFQ5P--lAKxl?!D$$2n%xX(`|l=uY#a>a>1ij;9~{a7pWRx9;-D?NGqhL@iF zdFt`@?_d1!l~;J+6~6WgWjL}b6gbx48pi?(SU~+Ai602$iW7eHcxNVj&1c%_rqiItl+JokUO`2LNqC!|5*&30xM#8V!y5g7z5^nEmhBxNenb!i mNR05Ri(U!;7JAct(eKNng6yN4