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

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