Skip to content

service layer for invites and attempts #21

@adarshm11

Description

@adarshm11

Invite & Attempt Logic — Backend

Routes are wired in main.go and stub handlers exist in internal/handlers/invites.go and internal/handlers/attempts.go, but every handler returns placeholder JSON. All business logic needs to be implemented.


Already done

  • Route registration in main.go for all invite/attempt endpoints
  • Stub handler functions: CreateInvite, ListInvites, ValidateInvite, StartAttempt, ListAttempts, GetAttempt, GetAttemptQuestions, SaveAnswers, SubmitAttempt

Remaining work

Service layer

  • Create InviteService in internal/core/services/ with deps on InviteRepo, AttemptRepo, AssessmentRepo
  • Create AttemptService in internal/core/services/ with deps on AttemptRepo, AnswerRepo, QuestionRepo, SubmissionRepo

Invite handlers (internal/handlers/invites.go)

  • CreateInvite — parse assessment :id + JSON body (candidate_email), generate random invite_token (uuid or crypto/rand hex), insert via InviteRepo with status=pending and expires_at, return token + copyable link
  • ListInvites — call InviteRepo.ListByAssessmentID (filter by assessmentId query param), return array
  • ValidateInvite — look up by :token, check not expired and status is pending/started, return assessment metadata (title, description, duration, question count). Return 404/410 for invalid/expired tokens
  • StartAttempt — validate invite is pending, create AttemptRepo row with started_at=now, update invite status to "started", return attempt_id. Reject if already started (one-attempt rule)

Attempt handlers (internal/handlers/attempts.go)

  • ListAttempts — query by assessmentId query param (join through invites), return attempt list with email, status, total_score, timestamps
  • GetAttempt — return attempt details including remaining time (duration_minutes - elapsed since started_at)
  • GetAttemptQuestions — return all questions for this attempt's assessment (join invite -> assessment_template)
  • SaveAnswers — parse JSON body (question_id, response), upsert answer row via AnswerRepo. Validate attempt is in_progress and timer hasn't expired
  • SubmitAttempt — set status to submitted, set completed_at, auto-score MCQ/short-answer (compare response to correct_answer), sum total_score, update invite status to completed. Reject if already submitted or timer expired

DI wiring in main.go

  • Instantiate InviteService and AttemptService with repos
  • Pass services into handlers (same pattern as assessment handlers: SetXService() or handler struct)

Business rules

  • Invite can only be started once
  • Answers only saved while attempt is in_progress
  • Submit fails if attempt already submitted or timer expired
  • MCQ scoring: compare selected option(s) to correct_answer (all-or-nothing)

Note: this requires the completion of #17 and #18

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions