Skip to content

Commit 3a8d2f7

Browse files
authored
Implement voting functionality for congregational meeting
1 parent 3e4f33e commit 3a8d2f7

1 file changed

Lines changed: 145 additions & 0 deletions

File tree

Vote/Vote.py

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
import re
2+
from pprint import pprint
3+
4+
model.Title = "Congregational Meeting Ballot"
5+
model.Header = "Congregational Meeting Ballot"
6+
7+
pid = model.UserPeopleId
8+
person = model.GetPerson(pid)
9+
10+
meetingId = 34020
11+
12+
digitalSubgroup = "Digital"
13+
voteSubgroupPrefix = "Vote_"
14+
15+
votingOpen = False
16+
votingComplete = True
17+
18+
issues = {
19+
"sell": {
20+
"question": "Motion: The Trustees, along with the unanimous support of the Session, move that the congregation approve the sale of the 315 South 17th Street Building.",
21+
"options": ["Yes", "No", "Abstain"],
22+
"limit": 1 # this isn't supported yet, but feels like a good thing to include for later.
23+
}
24+
}
25+
26+
def getExistingVotes(voteKey):
27+
votesPrefix = voteSubgroupPrefix + voteKey + "_"
28+
query = """
29+
SELECT t3.Name as Subgroup
30+
FROM dbo.OrgMemMemTags AS t2
31+
INNER JOIN dbo.MemberTags AS t3 ON t3.Id = t2.MemberTagId
32+
INNER JOIN dbo.Meetings AS m ON t2.OrgId = m.OrganizationId
33+
WHERE m.MeetingId = {}
34+
AND t2.PeopleId = {}
35+
AND t3.Name LIKE '{}%';
36+
""".format(meetingId, pid, votesPrefix)
37+
38+
items = []
39+
for x in q.QuerySql(query):
40+
items.append({
41+
"Subgroup": x.Subgroup,
42+
"Vote": x.Subgroup[len(votesPrefix):]
43+
})
44+
45+
return items
46+
47+
def getOrgId():
48+
return q.QuerySqlInt("SELECT TOP 1 m.OrganizationId FROM Meetings m WHERE MeetingId={}".format(meetingId))
49+
50+
51+
# Communicant members 18+ (or unknown age)
52+
query = '''
53+
MemberStatusId = 10[Communicant Member]
54+
AND
55+
(
56+
Age = ''
57+
OR Age >= 18
58+
)
59+
AND PeopleId = {}
60+
'''.format(pid)
61+
62+
if Data.checkin == '1':
63+
orgId = getOrgId()
64+
65+
model.AddSubGroup(pid, orgId, digitalSubgroup)
66+
model.EditPersonAttendance(meetingId, pid, True)
67+
print "REDIRECT=/PyScript/Vote"
68+
69+
elif votingOpen and Data.vote != '':
70+
[key, vote] = Data.vote.split("_", 1)
71+
72+
# remove existing votes
73+
existing = getExistingVotes(key)
74+
orgId = getOrgId()
75+
if existing is not None:
76+
for x in existing:
77+
model.RemoveSubGroup(pid, orgId, x['Subgroup'])
78+
79+
subgroup = voteSubgroupPrefix + key + "_" + vote
80+
model.AddSubGroup(pid, orgId, subgroup)
81+
print "REDIRECT=/PyScript/Vote"
82+
83+
84+
# Check eligibility
85+
elif q.QueryCount(query) < 1:
86+
print "<p>You are not a Communicant Member of the church and/or are ineligible to vote in this meeting. If you believe this is a mistake, please talk to an elder.</p>"
87+
88+
else:
89+
query = '''
90+
SELECT TOP 1 a.MeetingId, a.OrganizationId, (1 * a.AttendanceFlag) as AttendanceFlag,
91+
1 * COALESCE((
92+
SELECT 1
93+
FROM dbo.OrgMemMemTags AS t2
94+
INNER JOIN dbo.MemberTags AS t3 ON t3.Id = t2.MemberTagId
95+
WHERE t3.Name = '{}'
96+
AND t2.OrgId = a.OrganizationId
97+
AND t2.PeopleId = a.PeopleId
98+
), 0) as Digital
99+
FROM Attend a WHERE PeopleId = {} AND MeetingId = {};
100+
'''.format(digitalSubgroup, pid, meetingId)
101+
102+
status = q.QuerySqlTop1(query)
103+
104+
# Check status
105+
if status is None or status.AttendanceFlag < 1:
106+
print "<p>You can check in for the meeting digitally here. <b>If you check in digitally, you MUST vote digitally</b> on this webpage. If you would rather vote with a paper ballot, DO NOT check in here, but instead go to check-in in Reception Hall.</p>"
107+
108+
print "<p><a href=\"?checkin=1\" class=\"btn btn-default\">Check In</a></p>"
109+
110+
elif status.Digital < 1:
111+
print "<p>You are checked in with a paper ballot and therefore may not vote digitally.</p>"
112+
113+
elif not votingOpen and not votingComplete:
114+
print "<p>You are checked in. Voting is closed until the question is called. Keep this tab open and come back to it to vote. You can lock your phone in the meantime.</p>"
115+
print "<script>setInterval(function() {location.reload();}, 10000);</script>"
116+
117+
elif not votingOpen and votingComplete:
118+
print "<p>Voting has been closed.</p>"
119+
120+
else:
121+
ii = 0
122+
for i in issues:
123+
ii = ii+1
124+
125+
votes = getExistingVotes(i)
126+
127+
print "<div class=\"well\">"
128+
print "<h2>Question {}: {}</h2>".format(ii, issues[i]['question'])
129+
130+
if len(votes) > 0:
131+
print "<p>Your vote has been recorded as shown.</p>"
132+
133+
for o in issues[i]['options']:
134+
optionKey = result = re.split(r'[^a-zA-Z]', o.lower(), maxsplit=1)[0]
135+
136+
active = False
137+
for v in votes:
138+
if v['Vote'] == optionKey:
139+
active = True
140+
break
141+
142+
print "<div style=\"margin-bottom:1em;\"><a class=\"btn {}\" style=\"width:100%; max-width:4in;\" href=\"?vote={}_{}\">{}</a></div>".format("btn-primary" if active else "btn-default", i, optionKey, o)
143+
144+
print "</div>"
145+
#

0 commit comments

Comments
 (0)