convert pdf to md, add OVERVIEW and docs
This commit is contained in:
@@ -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`
|
||||
Reference in New Issue
Block a user