convert pdf to md, add OVERVIEW and docs

This commit is contained in:
2026-08-17 22:30:18 +00:00
parent 95d5787868
commit 4df62d2609
44 changed files with 3307 additions and 1 deletions

View File

@@ -0,0 +1,76 @@
---
type: object
cluster: money
universe: live
status: verified
entity: app/models/earnings_summary.rb
---
# EarningsSummary
A plain Ruby object (**not** an Active Record model) that totals a
[portfolio](portfolio.md)'s earnings by reason for the "where did my money come from"
panel.
Verified 2026-08-16 against commit `63732df`.
## Why this shape
It lives in `app/models/` but has no table and no superclass
(`app/models/earnings_summary.rb:3`). It wraps a portfolio and runs one grouped sum per
reason (`:36-41`) — five queries per render, deliberately simple rather than a single
grouped query, because it is only ever built for one student at a time.
**Known defect — `transaction_fees_cents` always returns 0.** `sum_by_reason` filters
`.deposits`, i.e. `transaction_type: :deposit` (`:38`), but fee rows are written with
`transaction_type: :fee` by `TransactionFeeProcessor`
(`app/services/transaction_fee_processor.rb:26-29`). The two never intersect, so
`transaction_fees_cents` (`:30-32`) sums an empty set. It is rendered to students as
"Transaction Fees" at `app/views/portfolios/_earnings_summary_card.html.erb:22`, where it
always shows $0.00. The fix is to drop `.deposits` for that one reason — but note that
`total_earnings_cents` (`:26-28`) deliberately excludes fees, so changing `sum_by_reason`
wholesale would alter the total too.
## Shape
- PORO; `initialize(portfolio)` (`:6-8`)
- Readers, all in **cents**: `attendance_earnings_cents`, `reading_earnings_cents`,
`math_earnings_cents`, `awards_cents`, `total_earnings_cents`,
`transaction_fees_cents` (`:10-32`)
- `total_earnings_cents` = attendance + reading + math + awards (`:26-28`). Fees are
**not** subtracted.
- No caching, no memoization — each reader hits the database
It covers four of the seven `reason` values. `administrative_adjustments` and
`transaction_fees` are not part of the total; `grade_earnings` is leftover.
## Connected to
- **owns:** —
- **owned-by:** [portfolio](portfolio.md) (by construction, not by association)
- **joins:** reads [portfolio-transaction](portfolio-transaction.md)
- **looks-like-but-is-not:** not an Active Record model — `EarningsSummary.find` and any
scope or callback do not exist. It also is **not** the balance: it counts income only
and ignores debits, credits, and withdrawals entirely.
## If you change this
- **Hits:** `PortfoliosController#show` (`app/controllers/portfolios_controller.rb:10`)
and `Admin::StudentsController#show`
(`app/controllers/admin/students_controller.rb:21`); the two views that render it —
`app/views/portfolios/_earnings_summary_card.html.erb` and
`app/views/admin/students/show.html.erb:85-100`.
- **Does not hit:** [portfolio](portfolio.md)`#cash_balance`. This class is read-only and
entirely parallel to the balance calculation — correcting the fee bug here changes a
displayed figure, not anyone's spendable money.
## Surfaces
| Surface | Role |
|---|---|
| `PortfoliosController#show` | student/teacher read |
| `Admin::StudentsController#show` | admin read |
## See
- Source: `app/models/earnings_summary.rb`