Skip to content
question.go 2.45 KiB
Newer Older
Lo^2's avatar
Lo^2 committed
package model

import (
	"code.electrolab.fr/it/vote.electrolab.fr/service/db"
	"context"
	"fmt"
)

type Question struct {
	Name         string
	Position     int
	Title        string
	Sentence     string
	MinChoices   int
	MaxChoices   int
	VoteOpen     bool
	VoteCount    int
Lo^2's avatar
Lo^2 committed
	VotedAlready bool      // computed field if requesterUuid is provided
	Answers      []*Answer // might not be populated
Lo^2's avatar
Lo^2 committed
}

Lo^2's avatar
Lo^2 committed
func FetchQuestions(ctx context.Context, db db.Service, requesterUuid string) ([]*Question, error) {
Lo^2's avatar
Lo^2 committed
	return fetchQuestions(ctx, db, requesterUuid, "")
}

func FetchQuestion(ctx context.Context, db db.Service, requesterUuid, questionName string) (*Question, error) {
	if len(questionName) == 0 {
		return nil, fmt.Errorf("Question name not provided")
	}
	result, err := fetchQuestions(ctx, db, requesterUuid, questionName)
	if err != nil {
		return nil, err
	}
	if len(result) == 0 {
		return nil, nil
Lo^2's avatar
Lo^2 committed
	} else if len(result) != 1 {
Lo^2's avatar
Lo^2 committed
		return nil, fmt.Errorf("Invalid number of questions returned: %d", len(result))
	}
Lo^2's avatar
Lo^2 committed

	question := result[0]

	question.Answers, err = FetchAnswers(ctx, db, questionName)
	if err != nil {
		return nil, err
	}

	return question, nil
Lo^2's avatar
Lo^2 committed
}

func fetchQuestions(ctx context.Context, db db.Service, requesterUuid, questionName string) ([]*Question, error) {
	var (
		err  error
		args []interface{}
	)
	q := `
		SELECT
			name,
			position,
			title,
			sentence,
			min_choices,
			COALESCE(max_choices, -1),
			vote_open,
			vote_count,
	`
	if len(requesterUuid) > 0 {
		args = append(args, requesterUuid)
		q += fmt.Sprintf(` COALESCE((SELECT TRUE FROM votes WHERE votes.question_name=questions.name AND user_uuid=$%d), FALSE) as voted_already `, len(args))
	} else {
		q += ` FALSE as voted_already `
	}

	q += ` FROM questions `

	if len(questionName) > 0 {
		args = append(args, questionName)
		q += fmt.Sprintf(` WHERE name = $%d `, len(args))
	}

	q += ` ORDER BY position `

	var result []*Question
	rows, err := db.QueryContext(ctx, q, args...)
	if err != nil {
		return nil, fmt.Errorf("Error fetching question: %w", err)
	}
	defer rows.Close()

	for rows.Next() {
		question := new(Question)
		err = rows.Scan(
			&question.Name,
			&question.Position,
			&question.Title,
			&question.Sentence,
			&question.MinChoices,
			&question.MaxChoices,
			&question.VoteOpen,
			&question.VoteCount,
			&question.VotedAlready,
		)
		if err != nil {
			return nil, fmt.Errorf("Error fetching questions: %w", err)
		}
		result = append(result, question)
	}
	return result, nil
}