|
| 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