4.9 KiB
4.9 KiB
effects — if you are changing X, open these
One job: turn "I am about to change X" into a short list of cards to read first. This file is an index only. It holds no facts — if it disagrees with a card, the card is right and this file is stale.
Inputs
- Reference:
../objects/_index.md,../processes/CONTEXT.md - Reference:
../CONTEXT.md— read the traps before any change to money or rosters
Read first, always
Four things are true of this codebase and wrong in most people's mental model. All four
are in ../CONTEXT.md:
- A student's classroom has two rival sources of truth.
- Money is integer cents — except
Portfolio#cash_balance, which returns dollars. - Cash is never stored; the balance includes pending orders.
- The Alpha Vantage key is read two different ways with two different fallbacks.
By what you are changing
| If you are changing… | Open | Then check |
|---|---|---|
| anything with a balance | portfolio, portfolio-transaction | every _cents vs dollars boundary; pending-order subtraction |
| order placement or execution | order, place-and-execute-order | model validations and ExecuteOrder — they duplicate each other |
| the trading fee | portfolio-transaction, order | fee is per user per sweep, and Portfolio anticipates exactly one |
| holdings or share counts | portfolio-stock, portfolio-position | lots are append-only; sells are negative rows |
| stock prices or the API | stock, refresh-market-data | the two key lookups; the six auto-overwritten columns |
| payout amounts | grade-entry, finalize-gradebook-earnings | constants are code, not config; GRADE_OPTIONS order is load-bearing |
| gradebook workflow or status | grade-book | the completed? guard is the only double-pay protection; finalize is admin-only |
| rosters or enrollment | classroom-enrollment, classroom, student | both roster paths, every time |
| the school-year skeleton | school-year, quarter, year | the two auto-create cascades; the "YYYY - YYYY" string format |
| login, roles, or permissions | user, authenticate-authorize | username-not-email; /admin bypasses Pundit; verify_authorized is off |
| a scheduled job | processes/CONTEXT.md, config/recurring.yml |
jobs bypass authorization entirely |
| charts or history | portfolio-snapshot, snapshot-portfolio-worth | history is unrecoverable if a month is missed |
| creating students in bulk | import-students, student | classroom_id drives the enrollment callback |
| announcements | announcement | body column is dead; content is Action Text |
Changes with a wider blast radius than they look
| Change | Why it spreads |
|---|---|
Portfolio#cash_balance return unit |
every caller converts by hand; there is no shared money type |
GradeEntry::GRADE_OPTIONS order |
improvement bonuses compare array indices |
users.classroom_id |
still joined by Order.for_teacher, Classroom#students, and redirects |
PortfolioTransaction enum values |
integer-backed; renumbering rewrites the meaning of existing rows |
Year#name format |
SQL ordering and quarter navigation both parse the string |
adding a before_action to ApplicationController |
runs on /admin too — Admin::BaseController inherits it |
Changes that are safer than they look
| Change | Why it is contained |
|---|---|
| editing a gradebook after finalize | deposits carry no link back; nothing recomputes |
| archiving a stock | sells still work; only buying is blocked |
| discarding a user | the ledger is untouched and still sums |
| deleting snapshots | charts break, balances do not |
editing app/controllers/schools_controller.rb |
it is a ghost — no route reaches it |
Human check
After a change, re-read the Does not hit line of every card you opened. That line is the one most likely to have gone stale, and a wrong "does not hit" is more expensive than a missing card.