summaryrefslogtreecommitdiff
path: root/models.go
diff options
context:
space:
mode:
authorJan Dittberner <jan@dittberner.info>2017-04-21 02:25:49 +0200
committerJan Dittberner <jan@dittberner.info>2017-04-22 00:14:08 +0200
commit2cac50ee86e70428aa06c99f5e009ceaaf1dbc13 (patch)
treeada4eb330be62598445480b6f40a5633ddfa922f /models.go
parentb6ad5d8ad327066b21bdb690f5a5017f6bed9740 (diff)
downloadcacert-boardvoting-2cac50ee86e70428aa06c99f5e009ceaaf1dbc13.tar.gz
cacert-boardvoting-2cac50ee86e70428aa06c99f5e009ceaaf1dbc13.tar.xz
cacert-boardvoting-2cac50ee86e70428aa06c99f5e009ceaaf1dbc13.zip
Implement proxy voting
Diffstat (limited to 'models.go')
-rw-r--r--models.go124
1 files changed, 109 insertions, 15 deletions
diff --git a/models.go b/models.go
index 5297cf2..dfc054d 100644
--- a/models.go
+++ b/models.go
@@ -26,6 +26,10 @@ const (
sqlGetNextPendingDecisionDue
sqlGetReminderVoters
sqlFindUnvotedDecisionsForVoter
+ sqlGetEnabledVoterById
+ sqlCreateVote
+ sqlLoadVote
+ sqlGetVotersForProxy
)
var sqlStatements = map[sqlKey]string{
@@ -67,6 +71,10 @@ SELECT voters.id, voters.name, voters.enabled, voters.reminder
FROM voters
JOIN emails ON voters.id=emails.voter
WHERE emails.address=$1 AND voters.enabled=1`,
+ sqlGetEnabledVoterById: `
+SELECT id, name, enabled, reminder
+FROM voters
+WHERE enabled=1 AND id=$1`,
sqlCountOlderThanDecision: `
SELECT COUNT(*) > 0 FROM decisions WHERE proposed < $1`,
sqlCountOlderThanUnvotedDecision: `
@@ -95,14 +103,23 @@ FROM decisions
WHERE decisions.status=0 AND :now > due`,
sqlGetNextPendingDecisionDue: `
SELECT due FROM decisions WHERE status=0 ORDER BY due LIMIT 1`,
+ sqlGetVotersForProxy: `
+SELECT id, name, reminder
+FROM voters WHERE enabled=1 AND id != $1 AND id NOT IN (SELECT voter FROM votes WHERE decision=$2)`,
sqlGetReminderVoters: `
SELECT id, name, reminder FROM voters WHERE enabled=1 AND reminder!='' AND reminder IS NOT NULL`,
sqlFindUnvotedDecisionsForVoter: `
SELECT tag, title, votetype, due
FROM decisions
WHERE status = 0 AND id NOT IN (SELECT decision FROM votes WHERE voter = $1)
-ORDER BY due ASC
-`,
+ORDER BY due ASC`,
+ sqlCreateVote: `
+INSERT INTO votes (decision, voter, vote, voted, notes)
+VALUES (:decision, :voter, :vote, :voted, :notes)`,
+ sqlLoadVote: `
+SELECT decision, voter, vote, voted, notes
+FROM votes
+WHERE decision=$1 AND voter=$2`,
}
var db *sqlx.DB
@@ -122,9 +139,9 @@ type VoteType uint8
type VoteStatus int8
type Decision struct {
- Id int
+ Id int64
Proposed time.Time
- ProponentId int `db:"proponent"`
+ ProponentId int64 `db:"proponent"`
Title string
Content string
Quorum int
@@ -137,12 +154,12 @@ type Decision struct {
}
type Email struct {
- VoterId int `db:"voter"`
+ VoterId int64 `db:"voter"`
Address string
}
type Voter struct {
- Id int
+ Id int64
Name string
Enabled bool
Reminder string // reminder email address
@@ -150,14 +167,6 @@ type Voter struct {
type VoteChoice int
-type Vote struct {
- DecisionId int `db:"decision"`
- VoterId int `db:"voter"`
- Vote VoteChoice
- Voted time.Time
- Notes string
-}
-
const (
voteAye = 1
voteNaye = -1
@@ -202,6 +211,18 @@ func (v VoteChoice) String() string {
}
}
+var VoteValues = map[string]VoteChoice{
+ "aye": voteAye,
+ "naye": voteNaye,
+ "abstain": voteAbstain,
+}
+
+var VoteChoices = map[int64]VoteChoice{
+ 1: voteAye,
+ 0: voteAbstain,
+ -1: voteNaye,
+}
+
const (
voteStatusDeclined = -1
voteStatusPending = 0
@@ -224,6 +245,43 @@ func (v VoteStatus) String() string {
}
}
+type Vote struct {
+ DecisionId int64 `db:"decision"`
+ VoterId int64 `db:"voter"`
+ Vote VoteChoice
+ Voted time.Time
+ Notes string
+}
+
+func (v *Vote) Save() (err error) {
+ insertVoteStmt, err := db.PrepareNamed(sqlStatements[sqlCreateVote])
+ if err != nil {
+ logger.Println("Error preparing statement:", err)
+ return
+ }
+ defer insertVoteStmt.Close()
+
+ _, err = insertVoteStmt.Exec(v)
+ if err != nil {
+ logger.Println("Error saving vote:", err)
+ return
+ }
+
+ getVoteStmt, err := db.Preparex(sqlStatements[sqlLoadVote])
+ if err != nil {
+ logger.Println("Error preparing statement:", err)
+ return
+ }
+ defer getVoteStmt.Close()
+
+ err = getVoteStmt.Get(v, v.DecisionId, v.VoterId)
+ if err != nil {
+ logger.Println("Error getting inserted vote:", err)
+ }
+
+ return
+}
+
type VoteSums struct {
Ayes int
Nayes int
@@ -569,7 +627,7 @@ func (d *Decision) Close() (err error) {
logger.Printf("WARNING wrong number of affected rows: %d (1 expected)\n", affectedRows)
}
- notifyMail <- &NotificationClosedDecision{decision: *d, voteSums: *voteSums}
+ NotifyMailChannel <- NewNotificationClosedDecision(d, voteSums)
return
}
@@ -671,3 +729,39 @@ func FindUnvotedDecisionsForVoter(voter *Voter) (decisions *[]Decision, err erro
return
}
+
+func GetVoterById(id int64) (voter *Voter, err error) {
+ getVoterByIdStmt, err := db.Preparex(sqlStatements[sqlGetEnabledVoterById])
+ if err != nil {
+ logger.Println("Error preparing statement:", err)
+ return
+ }
+ defer getVoterByIdStmt.Close()
+
+ voter = &Voter{}
+ if err = getVoterByIdStmt.Get(voter, id); err != nil {
+ logger.Println("Error getting voter:", err)
+ return
+ }
+
+ return
+}
+
+func GetVotersForProxy(proxy *Voter, decision *Decision) (voters *[]Voter, err error) {
+ getVotersForProxyStmt, err := db.Preparex(sqlStatements[sqlGetVotersForProxy])
+ if err != nil {
+ logger.Println("Error preparing statement:", err)
+ return
+ }
+ defer getVotersForProxyStmt.Close()
+
+ votersSlice := make([]Voter, 0)
+
+ if err = getVotersForProxyStmt.Select(&votersSlice, proxy.Id, decision.Id); err != nil {
+ logger.Println("Error getting voters for proxy:", err)
+ return
+ }
+ voters = &votersSlice
+
+ return
+}