summaryrefslogtreecommitdiff
path: root/models.go
diff options
context:
space:
mode:
Diffstat (limited to 'models.go')
-rw-r--r--models.go378
1 files changed, 164 insertions, 214 deletions
diff --git a/models.go b/models.go
index 35511ed..75473b4 100644
--- a/models.go
+++ b/models.go
@@ -106,7 +106,7 @@ WHERE decisions.status=0 AND :now > due`,
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)`,
+FROM voters WHERE enabled=1 AND id != $1`,
sqlGetReminderVoters: `
SELECT id, name, reminder FROM voters WHERE enabled=1 AND reminder!='' AND reminder IS NOT NULL`,
sqlFindUnvotedDecisionsForVoter: `
@@ -123,47 +123,6 @@ FROM votes
WHERE decision=$1 AND voter=$2`,
}
-var db *sqlx.DB
-
-func init() {
- failed_statements := make([]string, 0)
- for _, sqlStatement := range sqlStatements {
- var stmt *sqlx.Stmt
- stmt, err := db.Preparex(sqlStatement)
- if err != nil {
- logger.Criticalf("ERROR parsing statement %s: %s", sqlStatement, err)
- failed_statements = append(failed_statements, sqlStatement)
- }
- stmt.Close()
- }
- if len(failed_statements) > 0 {
- panic(fmt.Sprintf("%d statements failed", len(failed_statements)))
- }
-
- migrateConf := &goose.DBConf{
- MigrationsDir: config.MigrationsPath,
- Env: "production",
- Driver: goose.DBDriver{
- Name: "sqlite3",
- OpenStr: config.DatabaseFile,
- Import: "github.com/mattn/go-sqlite3",
- Dialect: &goose.Sqlite3Dialect{},
- },
- }
-
- latest, err := goose.GetMostRecentDBVersion(migrateConf.MigrationsDir)
- if err != nil {
- logger.Criticalf("getting the most recent database repository version failed: %s", err)
- panic(err)
- }
-
- err = goose.RunMigrationsOnDb(migrateConf, migrateConf.MigrationsDir, latest, db.DB)
- if err != nil {
- logger.Criticalf("running database migration failed: %s", err)
- panic(err)
- }
-}
-
type VoteType uint8
type VoteStatus int8
@@ -282,30 +241,86 @@ type Vote struct {
Notes string
}
-func (v *Vote) Save() (err error) {
- insertVoteStmt, err := db.PrepareNamed(sqlStatements[sqlCreateVote])
+type dbHandler struct {
+ db *sqlx.DB
+}
+
+var db *dbHandler
+
+func NewDB(database *sqlx.DB) *dbHandler {
+ handler := &dbHandler{db: database}
+ failed_statements := make([]string, 0)
+ for _, sqlStatement := range sqlStatements {
+ var stmt *sqlx.Stmt
+ stmt, err := database.Preparex(sqlStatement)
+ if err != nil {
+ log.Critical("ERROR parsing statement %s: %s", sqlStatement, err)
+ failed_statements = append(failed_statements, sqlStatement)
+ }
+ stmt.Close()
+ }
+ if len(failed_statements) > 0 {
+ log.Panicf("%d statements failed to prepare", len(failed_statements))
+ }
+
+ migrateConf := &goose.DBConf{
+ MigrationsDir: config.MigrationsPath,
+ Env: "production",
+ Driver: goose.DBDriver{
+ Name: "sqlite3",
+ OpenStr: config.DatabaseFile,
+ Import: "github.com/mattn/go-sqlite3",
+ Dialect: &goose.Sqlite3Dialect{},
+ },
+ }
+
+ latest, err := goose.GetMostRecentDBVersion(migrateConf.MigrationsDir)
if err != nil {
- logger.Errorf("preparing statement failed: %s", err)
- return
+ log.Panicf("getting the most recent database repository version failed: %v", err)
}
- defer insertVoteStmt.Close()
- _, err = insertVoteStmt.Exec(v)
+ err = goose.RunMigrationsOnDb(migrateConf, migrateConf.MigrationsDir, latest, database.DB)
if err != nil {
- logger.Errorf("saving vote failed: %s", err)
- return
+ log.Panicf("running database migration failed: %v", err)
}
+ return handler
+}
+
+func (d *dbHandler) Close() error {
+ return d.db.Close()
+}
+
+func (d *dbHandler) getPreparedNamedStatement(statementKey sqlKey) *sqlx.NamedStmt {
+ statement, err := d.db.PrepareNamed(sqlStatements[statementKey])
+ if err != nil {
+ log.Panicf("Preparing statement failed: %v", err)
+ }
+ return statement
+}
- getVoteStmt, err := db.Preparex(sqlStatements[sqlLoadVote])
+func (d *dbHandler) getPreparedStatement(statementKey sqlKey) *sqlx.Stmt {
+ statement, err := d.db.Preparex(sqlStatements[statementKey])
if err != nil {
- logger.Errorf("preparing statement failed: %s", err)
+ log.Panicf("Preparing statement failed: %v", err)
+ }
+ return statement
+}
+
+func (v *Vote) Save() (err error) {
+ insertVoteStmt := db.getPreparedNamedStatement(sqlCreateVote)
+ defer insertVoteStmt.Close()
+
+ if _, err = insertVoteStmt.Exec(v); err != nil {
+ log.Errorf("saving vote failed: %v", err)
return
}
+
+ getVoteStmt := db.getPreparedStatement(sqlLoadVote)
defer getVoteStmt.Close()
- err = getVoteStmt.Get(v, v.DecisionId, v.VoterId)
- if err != nil {
- logger.Errorf("getting inserted vote failed: %s", err)
+ if err = getVoteStmt.Get(v, v.DecisionId, v.VoterId); err != nil {
+ log.Errorf("getting inserted vote failed: %v", err)
+ return
}
return
@@ -333,6 +348,17 @@ func (v *VoteSums) Percent() int {
return v.Ayes * 100 / totalVotes
}
+func (v *VoteSums) CalculateResult(quorum int, majority int) (status VoteStatus, reasoning string) {
+ if v.VoteCount() < quorum {
+ status, reasoning = voteStatusDeclined, fmt.Sprintf("Needed quorum of %d has not been reached.", quorum)
+ } else if (v.Ayes / v.TotalVotes()) < (majority / 100) {
+ status, reasoning = voteStatusDeclined, fmt.Sprintf("Needed majority of %d%% has not been reached.", majority)
+ } else {
+ status, reasoning = voteStatusApproved, "Quorum and majority have been reached"
+ }
+ return
+}
+
type VoteForDisplay struct {
Vote
Name string
@@ -346,11 +372,7 @@ type DecisionForDisplay struct {
}
func FindDecisionForDisplayByTag(tag string) (decision *DecisionForDisplay, err error) {
- decisionStmt, err := db.Preparex(sqlStatements[sqlLoadDecisionByTag])
- if err != nil {
- logger.Errorf("preparing statement failed: %s", err)
- return
- }
+ decisionStmt := db.getPreparedStatement(sqlLoadDecisionByTag)
defer decisionStmt.Close()
decision = &DecisionForDisplay{}
@@ -359,7 +381,8 @@ func FindDecisionForDisplayByTag(tag string) (decision *DecisionForDisplay, err
decision = nil
err = nil
} else {
- logger.Errorf("getting motion %s failed: %v", tag, err)
+ log.Errorf("getting motion %s failed: %v", tag, err)
+ return
}
}
decision.VoteSums, err = decision.Decision.VoteSums()
@@ -374,13 +397,9 @@ func FindDecisionForDisplayByTag(tag string) (decision *DecisionForDisplay, err
func FindDecisionsForDisplayOnPage(page int64, unvoted bool, voter *Voter) (decisions []*DecisionForDisplay, err error) {
var decisionsStmt *sqlx.Stmt
if unvoted && voter != nil {
- decisionsStmt, err = db.Preparex(sqlStatements[sqlLoadUnvotedDecisions])
+ decisionsStmt = db.getPreparedStatement(sqlLoadUnvotedDecisions)
} else {
- decisionsStmt, err = db.Preparex(sqlStatements[sqlLoadDecisions])
- }
- if err != nil {
- logger.Errorf("preparing statement failed: %s", err)
- return
+ decisionsStmt = db.getPreparedStatement(sqlLoadDecisions)
}
defer decisionsStmt.Close()
@@ -391,7 +410,7 @@ func FindDecisionsForDisplayOnPage(page int64, unvoted bool, voter *Voter) (deci
rows, err = decisionsStmt.Queryx(page - 1)
}
if err != nil {
- logger.Errorf("loading motions for page %d failed: %v", page, err)
+ log.Errorf("loading motions for page %d failed: %v", page, err)
return
}
defer rows.Close()
@@ -399,7 +418,7 @@ func FindDecisionsForDisplayOnPage(page int64, unvoted bool, voter *Voter) (deci
for rows.Next() {
var d DecisionForDisplay
if err = rows.StructScan(&d); err != nil {
- logger.Errorf("loading motions for page %d failed: %v", page, err)
+ log.Errorf("loading motions for page %d failed: %v", page, err)
return
}
d.VoteSums, err = d.Decision.VoteSums()
@@ -412,16 +431,12 @@ func FindDecisionsForDisplayOnPage(page int64, unvoted bool, voter *Voter) (deci
}
func (d *Decision) VoteSums() (sums *VoteSums, err error) {
- votesStmt, err := db.Preparex(sqlStatements[sqlLoadVoteCountsForDecision])
- if err != nil {
- logger.Errorf("preparing statement failed: %s", err)
- return
- }
+ votesStmt := db.getPreparedStatement(sqlLoadVoteCountsForDecision)
defer votesStmt.Close()
voteRows, err := votesStmt.Queryx(d.Id)
if err != nil {
- logger.Errorf("fetching vote sums for motion %s failed: %v", d.Tag, err)
+ log.Errorf("fetching vote sums for motion %s failed: %v", d.Tag, err)
return
}
defer voteRows.Close()
@@ -431,7 +446,7 @@ func (d *Decision) VoteSums() (sums *VoteSums, err error) {
var vote VoteChoice
var count int
if err = voteRows.Scan(&vote, &count); err != nil {
- logger.Errorf("fetching vote sums for motion %s failed: %v", d.Tag, err)
+ log.Errorf("fetching vote sums for motion %s failed: %v", d.Tag, err)
return
}
switch vote {
@@ -447,39 +462,33 @@ func (d *Decision) VoteSums() (sums *VoteSums, err error) {
}
func (d *DecisionForDisplay) LoadVotes() (err error) {
- votesStmt, err := db.Preparex(sqlStatements[sqlLoadVotesForDecision])
- if err != nil {
- logger.Errorf("preparing statement failed: %s", err)
- return
- }
+ votesStmt := db.getPreparedStatement(sqlLoadVotesForDecision)
defer votesStmt.Close()
+
err = votesStmt.Select(&d.Votes, d.Id)
if err != nil {
- logger.Errorf("selecting votes for motion %s failed: %v", d.Tag, err)
+ log.Errorf("selecting votes for motion %s failed: %v", d.Tag, err)
+ return
}
return
}
func (d *Decision) OlderExists(unvoted bool, voter *Voter) (result bool, err error) {
- var olderStmt *sqlx.Stmt
if unvoted && voter != nil {
- olderStmt, err = db.Preparex(sqlStatements[sqlCountOlderThanUnvotedDecision])
- } else {
- olderStmt, err = db.Preparex(sqlStatements[sqlCountOlderThanDecision])
- }
- if err != nil {
- logger.Errorf("preparing statement failed: %s", err)
- return
- }
- defer olderStmt.Close()
+ olderStmt := db.getPreparedStatement(sqlCountOlderThanUnvotedDecision)
+ defer olderStmt.Close()
- if unvoted && voter != nil {
if err = olderStmt.Get(&result, d.Proposed, voter.Id); err != nil {
- logger.Errorf("finding older motions than %s failed: %v", d.Tag, err)
+ log.Errorf("finding older motions than %s failed: %v", d.Tag, err)
+ return
}
} else {
+ olderStmt := db.getPreparedStatement(sqlCountOlderThanDecision)
+ defer olderStmt.Close()
+
if err = olderStmt.Get(&result, d.Proposed); err != nil {
- logger.Errorf("finding older motions than %s failed: %v", d.Tag, err)
+ log.Errorf("finding older motions than %s failed: %v", d.Tag, err)
+ return
}
}
@@ -487,76 +496,62 @@ func (d *Decision) OlderExists(unvoted bool, voter *Voter) (result bool, err err
}
func (d *Decision) Create() (err error) {
- insertDecisionStmt, err := db.PrepareNamed(sqlStatements[sqlCreateDecision])
- if err != nil {
- logger.Errorf("preparing statement failed: %s", err)
- return
- }
+ insertDecisionStmt := db.getPreparedNamedStatement(sqlCreateDecision)
defer insertDecisionStmt.Close()
result, err := insertDecisionStmt.Exec(d)
if err != nil {
- logger.Errorf("creating motion failed: %s", err)
+ log.Errorf("creating motion failed: %v", err)
return
}
lastInsertId, err := result.LastInsertId()
if err != nil {
- logger.Errorf("getting id of inserted motion failed: %s", err)
+ log.Errorf("getting id of inserted motion failed: %v", err)
return
}
rescheduleChannel <- JobIdCloseDecisions
- getDecisionStmt, err := db.Preparex(sqlStatements[sqlLoadDecisionById])
- if err != nil {
- logger.Errorf("preparing statement failed: %s", err)
- return
- }
+ getDecisionStmt := db.getPreparedStatement(sqlLoadDecisionById)
defer getDecisionStmt.Close()
err = getDecisionStmt.Get(d, lastInsertId)
if err != nil {
- logger.Errorf("getting inserted motion failed: %s", err)
+ log.Errorf("getting inserted motion failed: %v", err)
+ return
}
return
}
func (d *Decision) LoadWithId() (err error) {
- getDecisionStmt, err := db.Preparex(sqlStatements[sqlLoadDecisionById])
- if err != nil {
- logger.Errorf("preparing statement failed: %s", err)
- return
- }
+ getDecisionStmt := db.getPreparedStatement(sqlLoadDecisionById)
defer getDecisionStmt.Close()
err = getDecisionStmt.Get(d, d.Id)
if err != nil {
- logger.Errorf("loading updated motion failed: %s", err)
+ log.Errorf("loading updated motion failed: %v", err)
+ return
}
return
}
func (d *Decision) Update() (err error) {
- updateDecisionStmt, err := db.PrepareNamed(sqlStatements[sqlUpdateDecision])
- if err != nil {
- logger.Errorf("preparing statement failed: %s", err)
- return
- }
+ updateDecisionStmt := db.getPreparedNamedStatement(sqlUpdateDecision)
defer updateDecisionStmt.Close()
result, err := updateDecisionStmt.Exec(d)
if err != nil {
- logger.Errorf("updating motion failed: %s", err)
+ log.Errorf("updating motion failed: %v", err)
return
}
affectedRows, err := result.RowsAffected()
if err != nil {
- logger.Errorf("Problem determining the affected rows")
+ log.Error("Problem determining the affected rows")
return
} else if affectedRows != 1 {
- logger.Warningf("wrong number of affected rows: %d (1 expected)", affectedRows)
+ log.Warningf("wrong number of affected rows: %d (1 expected)", affectedRows)
}
rescheduleChannel <- JobIdCloseDecisions
@@ -565,24 +560,20 @@ func (d *Decision) Update() (err error) {
}
func (d *Decision) UpdateStatus() (err error) {
- updateStatusStmt, err := db.PrepareNamed(sqlStatements[sqlUpdateDecisionStatus])
- if err != nil {
- logger.Errorf("preparing statement failed: %s", err)
- return
- }
+ updateStatusStmt := db.getPreparedNamedStatement(sqlUpdateDecisionStatus)
defer updateStatusStmt.Close()
result, err := updateStatusStmt.Exec(d)
if err != nil {
- logger.Errorf("setting motion status failed: %s", err)
+ log.Errorf("setting motion status failed: %v", err)
return
}
affectedRows, err := result.RowsAffected()
if err != nil {
- logger.Errorf("determining the affected rows failed: %s", err)
+ log.Errorf("determining the affected rows failed: %v", err)
return
} else if affectedRows != 1 {
- logger.Warningf("wrong number of affected rows: %d (1 expected)", affectedRows)
+ log.Warningf("wrong number of affected rows: %d (1 expected)", affectedRows)
}
rescheduleChannel <- JobIdCloseDecisions
@@ -595,17 +586,13 @@ func (d *Decision) String() string {
}
func FindVoterByAddress(emailAddress string) (voter *Voter, err error) {
- findVoterStmt, err := db.Preparex(sqlStatements[sqlLoadEnabledVoterByEmail])
- if err != nil {
- logger.Errorf("preparing statement failed: %s", err)
- return
- }
+ findVoterStmt := db.getPreparedStatement(sqlLoadEnabledVoterByEmail)
defer findVoterStmt.Close()
voter = &Voter{}
if err = findVoterStmt.Get(voter, emailAddress); err != nil {
if err != sql.ErrNoRows {
- logger.Errorf("getting voter for address %s failed: %v", emailAddress, err)
+ log.Errorf("getting voter for address %s failed: %v", emailAddress, err)
} else {
err = nil
voter = nil
@@ -614,72 +601,56 @@ func FindVoterByAddress(emailAddress string) (voter *Voter, err error) {
return
}
-func (d *Decision) Close() (err error) {
+func (d *Decision) Close() error {
quorum, majority := d.VoteType.QuorumAndMajority()
- voteSums, err := d.VoteSums()
-
- if err != nil {
- logger.Errorf("getting vote sums failed: %s", err)
- return
- }
- votes := voteSums.VoteCount()
+ var voteSums *VoteSums
+ var err error
- if votes < quorum {
- d.Status = voteStatusDeclined
- } else {
- votes = voteSums.TotalVotes()
- if (voteSums.Ayes / votes) > (majority / 100) {
- d.Status = voteStatusApproved
- } else {
- d.Status = voteStatusDeclined
- }
+ if voteSums, err = d.VoteSums(); err != nil {
+ log.Errorf("getting vote sums failed: %v", err)
+ return err
}
+ var reasoning string
+ d.Status, reasoning = voteSums.CalculateResult(quorum, majority)
- closeDecisionStmt, err := db.PrepareNamed(sqlStatements[sqlUpdateDecisionStatus])
- if err != nil {
- logger.Errorf("preparing statement failed: %s", err)
- return
- }
+ closeDecisionStmt := db.getPreparedNamedStatement(sqlUpdateDecisionStatus)
defer closeDecisionStmt.Close()
result, err := closeDecisionStmt.Exec(d)
if err != nil {
- logger.Errorf("closing vote failed: %s", err)
- return
- }
- affectedRows, err := result.RowsAffected()
- if err != nil {
- logger.Errorf("getting affected rows failed: %s", err)
+ log.Errorf("closing vote failed: %v", err)
+ return err
}
- if affectedRows != 1 {
- logger.Warningf("wrong number of affected rows: %d (1 expected)", affectedRows)
+ if affectedRows, err := result.RowsAffected(); err != nil {
+ log.Errorf("getting affected rows failed: %v", err)
+ return err
+ } else if affectedRows != 1 {
+ log.Warningf("wrong number of affected rows: %d (1 expected)", affectedRows)
}
- NotifyMailChannel <- NewNotificationClosedDecision(d, voteSums)
+ NotifyMailChannel <- NewNotificationClosedDecision(d, voteSums, reasoning)
- return
+ log.Infof("decision %s closed with result %s: reasoning %s", d.Tag, d.Status, reasoning)
+
+ return nil
}
func CloseDecisions() (err error) {
- getClosableDecisionsStmt, err := db.PrepareNamed(sqlStatements[sqlSelectClosableDecisions])
- if err != nil {
- logger.Errorf("preparing statement failed: %s", err)
- return
- }
+ getClosableDecisionsStmt := db.getPreparedNamedStatement(sqlSelectClosableDecisions)
defer getClosableDecisionsStmt.Close()
decisions := make([]*Decision, 0)
rows, err := getClosableDecisionsStmt.Queryx(struct{ Now time.Time }{time.Now().UTC()})
if err != nil {
- logger.Errorf("fetching closable decisions failed: %s", err)
+ log.Errorf("fetching closable decisions failed: %v", err)
return
}
defer rows.Close()
for rows.Next() {
decision := &Decision{}
if err = rows.StructScan(decision); err != nil {
- logger.Errorf("scanning row failed: %s", err)
+ log.Errorf("scanning row failed: %v", err)
return
}
decisions = append(decisions, decision)
@@ -687,9 +658,9 @@ func CloseDecisions() (err error) {
rows.Close()
for _, decision := range decisions {
- logger.Debugf("found closable decision %s", decision.Tag)
+ log.Debugf("found closable decision %s", decision.Tag)
if err = decision.Close(); err != nil {
- logger.Errorf("closing decision %s failed: %s", decision.Tag, err)
+ log.Errorf("closing decision %s failed: %s", decision.Tag, err)
return
}
}
@@ -698,41 +669,32 @@ func CloseDecisions() (err error) {
}
func GetNextPendingDecisionDue() (due *time.Time, err error) {
- getNextPendingDecisionDueStmt, err := db.Preparex(sqlStatements[sqlGetNextPendingDecisionDue])
- if err != nil {
- logger.Errorf("preparing statement failed: %s", err)
- return
- }
+ getNextPendingDecisionDueStmt := db.getPreparedStatement(sqlGetNextPendingDecisionDue)
defer getNextPendingDecisionDueStmt.Close()
row := getNextPendingDecisionDueStmt.QueryRow()
- var dueTimestamp time.Time
- if err = row.Scan(&dueTimestamp); err != nil {
+ due = &time.Time{}
+ if err = row.Scan(due); err != nil {
if err == sql.ErrNoRows {
- logger.Debugf("No pending decisions")
+ log.Debug("No pending decisions")
return nil, nil
}
- logger.Errorf("parsing result failed: %s", err)
- return
+ log.Errorf("parsing result failed: %v", err)
+ return nil, err
}
- due = &dueTimestamp
return
}
func GetReminderVoters() (voters *[]Voter, err error) {
- getReminderVotersStmt, err := db.Preparex(sqlStatements[sqlGetReminderVoters])
- if err != nil {
- logger.Errorf("preparing statement failed: %s", err)
- return
- }
+ getReminderVotersStmt := db.getPreparedStatement(sqlGetReminderVoters)
defer getReminderVotersStmt.Close()
voterSlice := make([]Voter, 0)
if err = getReminderVotersStmt.Select(&voterSlice); err != nil {
- logger.Errorf("getting voters failed: %s", err)
+ log.Errorf("getting voters failed: %v", err)
return
}
voters = &voterSlice
@@ -741,17 +703,13 @@ func GetReminderVoters() (voters *[]Voter, err error) {
}
func FindUnvotedDecisionsForVoter(voter *Voter) (decisions *[]Decision, err error) {
- findUnvotedDecisionsForVoterStmt, err := db.Preparex(sqlStatements[sqlFindUnvotedDecisionsForVoter])
- if err != nil {
- logger.Errorf("preparing statement failed: %s", err)
- return
- }
+ findUnvotedDecisionsForVoterStmt := db.getPreparedStatement(sqlFindUnvotedDecisionsForVoter)
defer findUnvotedDecisionsForVoterStmt.Close()
decisionsSlice := make([]Decision, 0)
if err = findUnvotedDecisionsForVoterStmt.Select(&decisionsSlice, voter.Id); err != nil {
- logger.Errorf("getting unvoted decisions failed: %s", err)
+ log.Errorf("getting unvoted decisions failed: %v", err)
return
}
decisions = &decisionsSlice
@@ -760,34 +718,26 @@ func FindUnvotedDecisionsForVoter(voter *Voter) (decisions *[]Decision, err erro
}
func GetVoterById(id int64) (voter *Voter, err error) {
- getVoterByIdStmt, err := db.Preparex(sqlStatements[sqlGetEnabledVoterById])
- if err != nil {
- logger.Errorf("preparing statement failed: %s", err)
- return
- }
+ getVoterByIdStmt := db.getPreparedStatement(sqlGetEnabledVoterById)
defer getVoterByIdStmt.Close()
voter = &Voter{}
if err = getVoterByIdStmt.Get(voter, id); err != nil {
- logger.Errorf("getting voter failed: %s", err)
+ log.Errorf("getting voter failed: %v", err)
return
}
return
}
-func GetVotersForProxy(proxy *Voter, decision *Decision) (voters *[]Voter, err error) {
- getVotersForProxyStmt, err := db.Preparex(sqlStatements[sqlGetVotersForProxy])
- if err != nil {
- logger.Errorf("preparing statement failed: %s", err)
- return
- }
+func GetVotersForProxy(proxy *Voter) (voters *[]Voter, err error) {
+ getVotersForProxyStmt := db.getPreparedStatement(sqlGetVotersForProxy)
defer getVotersForProxyStmt.Close()
votersSlice := make([]Voter, 0)
- if err = getVotersForProxyStmt.Select(&votersSlice, proxy.Id, decision.Id); err != nil {
- logger.Errorf("Error getting voters for proxy failed: %s", err)
+ if err = getVotersForProxyStmt.Select(&votersSlice, proxy.Id); err != nil {
+ log.Errorf("Error getting voters for proxy failed: %v", err)
return
}
voters = &votersSlice