convert pdf to md, add OVERVIEW and docs
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
---
|
||||
type: object
|
||||
cluster: gradebook
|
||||
universe: live
|
||||
status: verified
|
||||
entity: app/models/grade_entry.rb
|
||||
---
|
||||
|
||||
# GradeEntry
|
||||
|
||||
One student's row in one [grade-book](grade-book.md): two letter grades, attendance days,
|
||||
a perfect-attendance flag. **This is where every payout amount is defined.**
|
||||
|
||||
Verified 2026-08-16 against commit `63732df`.
|
||||
|
||||
## Why this shape
|
||||
|
||||
The payout table is five Ruby constants on this model, all in **cents**
|
||||
(`app/models/grade_entry.rb:9-13`):
|
||||
|
||||
| Constant | Value | Meaning |
|
||||
|---|---|---|
|
||||
| `EARNINGS_PER_DAY_ATTENDANCE` | `20` | $0.20 per day present |
|
||||
| `EARNINGS_FOR_A_GRADE` | `3_00` | $3.00 for any A |
|
||||
| `EARNINGS_FOR_B_GRADE` | `2_00` | $2.00 for any B |
|
||||
| `EARNINGS_FOR_IMPROVED_GRADE` | `2_00` | $2.00 for improving |
|
||||
| `EARNINGS_FOR_PERFECT_ATTENDANCE` | `1_00` | $1.00 bonus |
|
||||
|
||||
They are not configuration. Changing what a student earns is a code change and a deploy —
|
||||
there is no admin screen and no database row for these.
|
||||
|
||||
**`GRADE_OPTIONS` is ordered best-to-worst on purpose** (`:15`). `improved_grade?`
|
||||
compares array *indices*, treating a lower index as better (`:64-67`). Reordering or
|
||||
inserting into that array silently changes every improvement bonus in the app.
|
||||
|
||||
**There are no validations on this model at all** — grades are constrained only by the
|
||||
`<select>` in `app/views/grade_books/_grade_entry.html.erb:8,17`, and the controller
|
||||
permits the values straight through (`app/controllers/grade_books_controller.rb:53-57`).
|
||||
A value outside `GRADE_OPTIONS` saves fine, then makes `improved_grade?` compare `nil`
|
||||
indices and raise `NoMethodError` during the next quarter's payout. Grades C through F
|
||||
earn nothing but are legal; anything not in the list is a latent failure.
|
||||
|
||||
## Shape
|
||||
|
||||
- Table `grade_entries`, `db/schema.rb:109-121`; unique on `[grade_book_id, user_id]`
|
||||
(`db/schema.rb:118`) — one row per student per book
|
||||
- `math_grade`, `reading_grade` — plain strings, nullable, unvalidated
|
||||
- `attendance_days` — bigint, nullable; `earnings_for_attendance` returns 0 when blank
|
||||
(`:17-21`)
|
||||
- `is_perfect_attendance` — boolean, default false, `null: false` (`db/schema.rb:113`)
|
||||
- `belongs_to :grade_book`, `belongs_to :user` (`:4-5`) — `user`, not `student`
|
||||
- Earnings readers: `earnings_for_attendance`, `earnings_for_math`,
|
||||
`earnings_for_reading`, `attendance_perfect_earnings`, `math_improvement_earnings`,
|
||||
`reading_improvement_earnings` (`:17-49`)
|
||||
|
||||
Every earnings method is a **pure reader**. Nothing here writes money —
|
||||
`DistributeEarnings` calls them and creates the deposits.
|
||||
|
||||
## Connected to
|
||||
|
||||
- **owns:** —
|
||||
- **owned-by:** [grade-book](grade-book.md), [user](../identity/user.md)
|
||||
- **joins:** —
|
||||
- **looks-like-but-is-not:** `math_grade` is a **letter** (`"A+"`…`"F"`), unrelated to
|
||||
[grade-level](../org/grade-level.md), which is 5–8.
|
||||
|
||||
## If you change this
|
||||
|
||||
- **Hits:** [portfolio-transaction](../money/portfolio-transaction.md) amounts — these
|
||||
constants are the amounts; `DistributeEarnings`
|
||||
(`app/services/distribute_earnings.rb:54-73`), which sums attendance + math + reading;
|
||||
the [finalize-gradebook-earnings](../../processes/finalize-gradebook-earnings.md)
|
||||
movement; `AttendanceEntryPresenter`.
|
||||
- **Does not hit:** already-paid deposits. Editing an entry after finalize changes
|
||||
nothing retroactively — the deposits are independent rows with no link back to the
|
||||
entry that produced them (`db/schema.rb:170-179` has no `grade_entry_id`). Re-paying
|
||||
would require re-running finalize, which the `completed?` guard blocks.
|
||||
|
||||
## Surfaces
|
||||
|
||||
| Surface | Role |
|
||||
|---|---|
|
||||
| `GradeBooksController#update` (+ autosave Stimulus controller) | teacher writes |
|
||||
| `DistributeEarnings` | reads |
|
||||
| `AttendanceEntryPresenter` | reads |
|
||||
|
||||
## See
|
||||
|
||||
- Source: `app/models/grade_entry.rb`, `db/schema.rb:109-121`
|
||||
- As-built: `docs/gradebook-earnings.md`
|
||||
Reference in New Issue
Block a user