summaryrefslogtreecommitdiff
path: root/models.go
diff options
context:
space:
mode:
Diffstat (limited to 'models.go')
-rw-r--r--models.go85
1 files changed, 85 insertions, 0 deletions
diff --git a/models.go b/models.go
index d6eee15..5df7d95 100644
--- a/models.go
+++ b/models.go
@@ -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
+}