Files
project-work/worker-toolkit-stocks-in-the-future/repo/docs/map/objects/gradebook/grade-book.md

3.1 KiB

type, cluster, universe, status, entity
type cluster universe status entity
object gradebook live verified app/models/grade_book.rb

GradeBook

One classroom's grades for one quarter, and the object whose status decides whether students get paid.

Verified 2026-08-16 against commit 63732df.

Why this shape

The model is tiny — two belongs-to, one has-many, one enum (app/models/grade_book.rb) — but the enum is the payout gate.

status has three values: draft → verified → completed (:8-12). Read literally that looks like a review workflow. It is not. GradeBooksController#finalize sets verified! and calls DistributeEarnings on the very next line (app/controllers/grade_books_controller.rb:30-31), so verified exists for a few milliseconds. Its real job is to satisfy the service's own guard, return unless @grade_book.verified? (app/services/distribute_earnings.rb:14), which keeps the service safe to call from anywhere else.

Double-payment is prevented by exactly one check — the controller's if @grade_book.completed? (app/controllers/grade_books_controller.rb:26). There is no database constraint, no idempotency key on the resulting deposits, and DistributeEarnings itself would happily pay twice if handed a verified book. Anything new that finalizes a gradebook must repeat that check.

Gradebooks are never created by a controller: classroom creates one per quarter on after_create (app/models/classroom.rb:29,112-116).

Shape

  • Table grade_books, db/schema.rb:98-107; unique on [quarter_id, classroom_id] (db/schema.rb:105) — one book per classroom per quarter
  • status is a string column, default "draft", null: false (db/schema.rb:102)
  • belongs_to :quarter, belongs_to :classroom (:4-5)
  • has_many :grade_entries, dependent: :destroy (:6)

Connected to

If you change this

Surfaces

Surface Role
GradeBooksController (show, update, finalize) teacher reads/writes
Classroom#create_gradebooks_for_quarters writes (creation)
DistributeEarnings reads status, writes completed!

See

  • Source: app/models/grade_book.rb, db/schema.rb:98-107
  • As-built: docs/gradebook-earnings.md