diff options
author | Jan Dittberner <jandd@cacert.org> | 2017-04-19 23:32:12 +0200 |
---|---|---|
committer | Jan Dittberner <jan@dittberner.info> | 2017-04-22 00:12:38 +0200 |
commit | 2de96dc13dc5e2843ebe204a7e1dfe6197ab7de0 (patch) | |
tree | e554bd4986e8803ed13daab5b61b35f11e06e826 /models.go | |
parent | 0ce9ad6dcc01375cb3f2d57f7bbdf701e605bea1 (diff) | |
download | cacert-boardvoting-2de96dc13dc5e2843ebe204a7e1dfe6197ab7de0.tar.gz cacert-boardvoting-2de96dc13dc5e2843ebe204a7e1dfe6197ab7de0.tar.xz cacert-boardvoting-2de96dc13dc5e2843ebe204a7e1dfe6197ab7de0.zip |
Implement vote closing, refactor notifications
Diffstat (limited to 'models.go')
-rw-r--r-- | models.go | 85 |
1 files changed, 85 insertions, 0 deletions
@@ -21,6 +21,7 @@ const ( sqlCreateDecision sqlUpdateDecision sqlUpdateDecisionStatus + sqlSelectClosableDecisions ) var sqlStatements = map[sqlKey]string{ @@ -103,6 +104,12 @@ WHERE id=:id`, UPDATE decisions SET status=:status, modified=:modified WHERE id=:id `, + sqlSelectClosableDecisions: ` +SELECT decisions.id, decisions.tag, decisions.proponent, voters.name AS proposer, decisions.proposed, decisions.title, + decisions.content, decisions.votetype, decisions.status, decisions.due, decisions.modified +FROM decisions +JOIN voters ON decisions.proponent=voters.id +WHERE decisions.status=0 AND :now > due`, } var db *sqlx.DB @@ -506,3 +513,81 @@ func FindVoterByAddress(emailAddress string) (voter *Voter, err error) { } return } + +func (d *Decision) Close() (err error) { + closeDecisionStmt, err := db.PrepareNamed(sqlStatements[sqlUpdateDecisionStatus]) + if err != nil { + logger.Println("Error preparing statement:", err) + return + } + defer closeDecisionStmt.Close() + + quorum, majority := d.VoteType.QuorumAndMajority() + + voteSums, err := d.VoteSums() + + if err != nil { + logger.Println("Error getting vote sums") + return + } + votes := voteSums.VoteCount() + + if votes < quorum { + d.Status = voteStatusDeclined + } else { + votes = voteSums.Ayes + voteSums.Nayes + if (voteSums.Ayes / votes) > (majority / 100) { + d.Status = voteStatusApproved + } else { + d.Status = voteStatusDeclined + } + } + + result, err := closeDecisionStmt.Exec(d) + if err != nil { + logger.Println("Error closing vote:", err) + return + } + affectedRows, err := result.RowsAffected() + if err != nil { + logger.Println("Error getting affected rows:", err) + } + if affectedRows != 1 { + logger.Printf("WARNING wrong number of affected rows: %d (1 expected)\n", affectedRows) + } + + notifyMail <- &NotificationClosedDecision{decision: *d, voteSums: *voteSums} + + return +} + +func CloseDecisions() (err error) { + getClosedDecisionsStmt, err := db.PrepareNamed(sqlStatements[sqlSelectClosableDecisions]) + if err != nil { + logger.Println("Error preparing statement:", err) + return + } + defer getClosedDecisionsStmt.Close() + + params := make(map[string]interface{}, 1) + params["now"] = time.Now().UTC() + rows, err := getClosedDecisionsStmt.Queryx(params) + if err != nil { + logger.Println("Error fetching closed decisions", err) + return + } + defer rows.Close() + for rows.Next() { + d := &Decision{} + if err = rows.StructScan(d); err != nil { + logger.Println("Error filling decision from database row", err) + return + } + if err = d.Close(); err != nil { + logger.Printf("Error closing decision %s: %s\n", d.Tag, err) + return + } + } + + return +} |