# Metro Nashville Operating Budget Books — department-level extraction

Extracted 31 Oct 2026 from the 12 PDFs in `raw/budget/` (FY2014, FY2015, FY2016, FY2019–FY2026 adopted books; FY2027 *recommended* book). The FY2017 and FY2018 books were not in the folder and were skipped — FY2017 and FY2018 figures therefore exist only as prior-year columns of later books (see "Coverage"). Scripts live in `scripts/budget/` (`run_all.sh` rebuilds everything; each `parse_*.py` writes its CSV plus a `validation_*.txt` log in this folder).

## Files

| file | rows | content |
|---|---|---|
| `schedule3_lines.csv` | 20,268 | Schedule 3 "Historical Expenditures": every printed line × 4 fiscal years (3 budget cols + 1 actual col). Columns: `book_fy, department_code, department_name, fund_group, business_unit_code, business_unit_name, fiscal_year, basis (actual/budget/recommended), amount, fte, is_total, row_type, code_printed, page`. |
| `schedule2_dept_by_fundtype.csv` | 4,188 | Schedule 2 "Departmental Budget by Fund Type" (budget year only), long by fund type: `GSD Budgetary Funds, USD Budgetary Funds, Special Revenue Funds, Enterprise Funds, Interfund Transfer, Dept Total`. `row_type` = department / debt_service_line / duplicated_transfers / nondept_line / total. |
| `schedule1_funds.csv` | 13,219 | Schedule 1 "Summary of Revenues and Expenditures": one block per budgetary fund (plus the "TOTAL - ALL BUDGETARY FUNDS" block) × 5 fiscal years (3 actual + 2 budget). `line_type` = revenue / expenditure / fund_balance / other; `is_total` marks TOTAL REVENUES / TOTAL EXPENDITURES / TOTAL OTHER FINANCING lines. |
| `book_headlines.csv` | 12 | Per book: six-fund total budget gross and net of interfund duplication (from the "Comparison of the FYxxxx and FYyyyy Budget Ordinances – Six (Tax Supported) Budgetary Funds" table), the six fund amounts, GSD / USD / combined property-tax rates (from "Property Tax Distribution (Rates per $100 of Assessed Value)"), total FTE (Schedule 3), Schedule 3 gross/net budgetary totals, source pages, notes. |
| `department_crosswalk.csv` | 67 | One row per department code: canonical name, names as printed (pipe-separated), first/last book, Schedule 3 fund groups, books present in Schedules 3 and 2, notes on renames/creations/moves. |
| `overlap_check.csv` | 716 | Same fiscal_year + basis compared across books for Schedule 3 department totals, fund totals, section/gross/net totals; `flag_gt_0_5pct` = 1 when books differ by more than 0.5%; one column per book. |
| `validation_schedule1/2/3.txt` | — | Full parse + arithmetic-check logs (every PROBLEM / rounding / book-error line referenced below). |

`row_type` in `schedule3_lines.csv`: `bu` (business unit, 8-digit code; only department 001 Administrative is printed at this level), `dept_total` (printed department line, 3-digit code), `dept_total_derived` (FY2014 book prints no 001 total — sum of its BU lines), `nondept_line` (FY2021 "Cash & Fund Balance Restoration" lines inside the GSD/USD general funds), `fund_total` (10101 GSD General, 20115 GSD Debt Service, 25104 MNPS Debt Service, 35131 MNPS General Purpose, 18301 USD General, 28315 USD Debt Service), `section_total` (TOTAL GSD BUDGETARY / TOTAL USD BUDGETARY / TOTAL SPECIAL REVENUE…), `gross_total`, `transfer_adj` + `net_total` (FY2014 only), `sr_fund` (one line per special revenue / enterprise / internal service / component-unit fund, 5-digit code), `sr_subtotal` ("Total NCAC Funds"), `fte_total` ("GROSS FTEs"). `is_total` = 1 for every total-type row (dept, fund, section, gross, net, subtotal, FTE total).

## Page map (pdf page numbers, 1-based)

| book | file | Schedule 1 | Schedule 2 | Schedule 3 | ordinance comparison | tax distribution |
|---|---|---|---|---|---|---|
| FY2014 | Budget_FY2014.pdf (781 pp) | 735–741 | 742–744 | 745–750 | 23 | 27 |
| FY2015 | Budget_FY2015.pdf (786) | 741–747 | 748–750 | 751–756 | 23 | 27 |
| FY2016 | Budget_FY2016.pdf (776) | 730–736 | 737–740 | 741–746 | 23 | 27 |
| FY2019 | Budget_FY2019.pdf (701) | 654–660 | 661–664 | 665–671 | 28 | 23 |
| FY2020 | Budget_FY2020.pdf (677) | 628–634 | 635–637 | 638–645 | 30 | 24 |
| FY2021 | Budget_FY2021.pdf (705) | 651–657 | 658–660 | 661–671 | 31 | 25 |
| FY2022 | Budget_FY2022.pdf (716) | 655–661 | 662–664 | 665–672 | 36 | 27 |
| FY2023 | Budget_FY2023.pdf (751) | 689–695 | 696–698 | 699–707 | 40 | 27 |
| FY2024 | Budget_FY2024.pdf (812) | 750–756 | 757–759 | 760–766 | 46 | 30 |
| FY2025 | Budget_FY2025.pdf (627) | 67–73 | 74–76 | 77–83 | 48 | 29 |
| FY2026 | Budget_FY2026.pdf (645) | 65–71 | 72–74 | 75–81 | 45 | 54 |
| FY2027 rec. | Budget_FY2027_Recommended.pdf (657) | 69–75 | 76–78 | 79–85 | 47 | 57 |

FY2014–FY2024 schedules sit in "Appendix 1: Financial Schedules" at the back; FY2025+ in Section B "Expenditures Overview: Financial Schedules".

## Column mapping

**Schedule 3** (book year Y): dollars = FY(Y-3) **Actuals**, FY(Y-2) Budget, FY(Y-1) Budget, FY(Y) Budget; FTE = FY(Y-2), FY(Y-1), FY(Y) plus a change column (dropped). No FTE is printed for the actuals year, so `fte` is blank on `basis=actual` rows. Printed labels of the budget-year column: FY2014/FY2015 "Final Budget"; FY2016 "Recommended Budget"; FY2019/FY2020 "REC Budget"; FY2021–FY2026 "Budget"; FY2027 "Budget" in a book titled *Recommended*. All books except FY2027 are the adopted operating budget books (published July–December after adoption), so their budget-year column is stored as `basis=budget`; the FY2027 book's FY2027 column is `basis=recommended`. The "REC"/"Recommended" labels in the FY2016/FY2019/FY2020 adopted books appear to be layout leftovers: e.g. FY2019 GSD General 969,874,000 in the FY2019 book equals the FY2019 adopted total in the ordinance comparison (2,230,100,600 net, which ties to Schedule 3). Verify against the ordinance if it matters.

**Schedule 1**: FY(Y-4), FY(Y-3), FY(Y-2) ACTUAL; FY(Y-1) BUDGET; FY(Y) BUDGET ("FINAL BUDGET" FY2014, "REC. BUDGET" FY2015/FY2016). FY2025–FY2027 text layers carry a stray trailing ")" on every number ("648,332,536)"), stripped. Fund block names as printed: GENERAL FUND - GSD, DEBT SERVICE - GSD, GENERAL PURPOSE SCHOOL FUND, SCHOOL DEBT SERVICE (FY2015+; FY2014 "SCHOOLS DEBT SERVICE…"), GENERAL FUND - USD, DEBT SERVICE - USD, TOTAL - ALL BUDGETARY FUNDS. Older books (FY2014–FY2020) have an OTHER FINANCING SOURCES (USES) section with Transfers in/out and fund-balance lines; FY2021+ fold Transfers In into revenues and Transfers Out into expenditures and print only "Excess (deficiency)" below the totals. Function names were re-labelled over time (Public welfare → Social Services; Public works, highway and streets → Infrastructure and Transportation; Conservation of natural resources folded into Recreation, Cultural, and Conservation (FY2015) then Recreation and Cultural). Line items are kept as printed; map them yourself if you aggregate by function.

**Schedule 2**: six numeric columns in every book (Budgetary GSD Funds, Budgetary USD Funds, Special Revenue Funds, Enterprise Funds, Interfund Transfer, Dept. Total). `fiscal_year` = book year. The FY2022 book's title reads "SCHEDULE 2 - FY2021 DEPARTMENTAL BUDGET BY FUND TYPE" — a typo: its GSD column total (2,490,756,500) equals the FY2022 TOTAL GSD BUDGETARY in Schedule 3, so it is the FY2022 budget. The 001 Administrative business-unit detail that Schedule 2 prints is skipped (it is in `schedule3_lines.csv`); only department-level rows are kept.

## Parsing approach

PyMuPDF words → visual rows by y-clustering → numeric tokens right of x=185 (Schedule 3) or right of the leftmost comma-number (Schedules 1/2) are values; columns are found by clustering the right edges of value tokens (right-aligned columns; 8/6/5 clusters). Wrapped labels are re-joined geometrically (the value baseline sits on the last line of a wrapped name in most books, on the first line in FY2023, and on its own line in a few FY2021 rows; FTE and dollar baselines are offset by ~4pt in FY2021–FY2023). Rows are classified by label pattern (8/10-digit business unit, 3/4-digit department, 5-digit fund, TOTAL/GROSS/NET keywords). "-" = 0; "na" = missing (FY2014 footnote "na - information not available at time of printing"); parentheses = negative; footnote asterisks stripped (`*` Gross totals include interfund duplications; `**` Transportation Licensing combined into Public Works for all years in FY2014–FY2016 books; `***` MNPS position counts cover all MNPS funds and were pending Board approval).

Code normalisation: the FY2027 book uses a new chart of accounts — 4-digit departments ("1001") and 10-digit business units ("1001101104"). `department_code` strips the leading "1" (1001 → 001) and 10-digit BU codes are mapped to the legacy 8-digit form (drop the first two digits: 1001101104 → 01101104); `code_printed` keeps the original. The FY2027 USD Administrative BU codes are printed truncated to 8 digits and repeat ("10011911 - …"); they are kept as printed. Schedule 2 FY2026 prints "D073 - East Bank Development Authority" → `department_code` 073 (`code_printed` D073); FY2027 prints the MNPS row without a code → 080.

Text-layer repairs (all logged in the validation files): a stray "0" glued to an amount ("11,127,1000" → 11,127,100; FY2024 Schedule 2); "2.474,946,700" period-for-comma typo (FY2021 Schedule 3 GROSS); three overrides where the PDF text layer lost digits — FY2021 Schedule 2 MNPS Special Revenue "315,310,60" → 315,310,600 (= TOTAL − other rows), FY2021 Schedule 1 all-funds TOTAL REVENUES FY2017 actual ",062,679,664" → 2,062,679,664, FY2024 Schedule 1 all-funds TOTAL EXPENDITURES FY2021 actual "203,677,128" → 2,303,677,128 (lines sum and Schedule 3 gross both give this). Lines printed twice with identical values (FY2014 Schedule 2 rows 063/064/065 across a page break; "General government" in FY2016 and FY2022 Schedule 1; "Fiscal Administration" in FY2022 Schedule 1; the 001 caption-with-values duplicate in FY2016/FY2019 Schedule 2) are dropped once.

## Validation results

**Schedule 3** (BU lines → department total; department totals → general-fund line 10101/18301; fund lines → TOTAL GSD/USD BUDGETARY; GSD+USD → GROSS; GROSS − transfers → NET (FY2014); special-revenue fund lines → TOTAL SPECIAL REVENUE where printed; every row has 4 dollar values). All books tie within $1 in all four columns except:
- actuals columns differ from printed totals by $2–$5 in nine places (FY2019, FY2021, FY2022, FY2023, FY2024, FY2025, FY2026, FY2027): the books print actuals rounded to dollars and totals computed from cents — reported as `rounding(book)`.
- **FY2019 book, page 667–668 (book-internal, could not reconcile):** 001 Administrative GSD BU lines sum to 327,578,500 / 356,843,200 vs printed totals 327,656,100 / 356,876,700 for FY2017 / FY2018 budgets (−77,600 / −33,500); and the FY2019 budget department totals sum to 969,251,300 vs the printed 10101 GSD General 969,874,000 (−622,700). Every printed BU/department line was captured (all have 8 values); the printed totals do not equal the printed detail.
- **FY2021 book, pp 665–671 (book-internal):** special-revenue fund lines sum to 1,926,693,344 for FY2018 actuals vs the printed TOTAL 1,918,650,256 (+8,043,088); the other three columns tie.
- FY2014–FY2016 books print no TOTAL SPECIAL REVENUE line; FY2019 lists NCAC only as "Total NCAC Funds" (ties when that subtotal is included). FY2014 book prints no 001 total lines (derived rows added).

**Schedule 2** (rows → TOTAL per column; fund types → Dept Total per row): FY2014, FY2015, FY2016, FY2022, FY2023, FY2025, FY2026, FY2027 tie exactly. Book-internal: FY2019 015 Finance Dept Total 10,142,300 vs fund types 10,141,900 (Enterprise column total off by the same 400); FY2020 064 Sports Authority prints 865,500 in both GSD and Special Revenue with Dept Total 865,500, and the Dept Total column total is 2,112,900 above the sum of rows; **FY2021 and FY2024 books: the printed "Dept. Total" column double-counts the Enterprise Funds column (12 and 11 rows) — use the fund-type columns, not Dept Total**; FY2021 001 Administrative USD prints 22,229,100 where the TOTAL row and Schedule 3 (25,229,100) imply 25,229,100 (−3,000,000), and the FY2021 "Cash & Fund Balance Restoration" line's Dept Total is 2,000,000 above its parts.

**Schedule 1** (lines → TOTAL REVENUES / TOTAL EXPENDITURES per fund and column): ties except book-internal items: FY2016 General Purpose School Fund revenue lines are short of the printed total in all five columns (a "Miscellaneous" line is missing from the printed page: −983,502 / −43,619 / −155,118 / −45,000 / −150,000); FY2019 School Fund FY2017 actual revenues +2,500,000; FY2019/FY2020 School Debt Service prints "Transfers Out" (57,284,896) / (95,432,894) for FY2015/FY2016 actuals that the printed TOTAL EXPENDITURES exclude; FY2021 book's FY2021-budget columns include un-itemised amounts in every fund's totals (GSD General +46,398,900 and USD General +7,168,600 = the "Cash & Fund Balance Restoration" lines of Schedule 3; debt and school funds +0.6M to +6.6M) and GSD General FY2020 budget −4,100; FY2022 all-funds page prints a "Transfers Out" row carrying the General Government values (199,784,141 …) that the TOTAL excludes; FY2023 USD General FY2022 budget "Compensation from Property" 100,000 not in the printed total.

**Headline total vs Schedule 3** (`book_headlines.csv`): the six-fund ordinance gross equals Schedule 3 GROSS BUDGETARY FUNDS exactly in FY2014, FY2016, FY2019, FY2020, FY2022, FY2025 and within $100 in FY2015/FY2023. Differences: FY2021 +3,023,000 (ordinance table shows the schools fund at 922,470,600, Schedule 1/3 at 925,493,600); FY2024 ordinance fund amounts include 74,991,200 of interfund transfers (ordinance net 3,289,323,600 ≈ Schedule 3 gross 3,288,693,500); FY2026 (−138,869,900) and FY2027 (−9,778,700) ordinance tables are on an appropriations basis that includes fund-balance/reserve items (FY2026 GSD General 1,857,113,900 = Schedule 1 total revenues vs 1,773,793,200 expenditures; GSD debt 304,561,400 vs 286,917,300; schools 1,413,018,500 vs 1,382,578,900; USD General 70,437,800 vs 67,728,600). Schedule 3 all-funds total (budgetary 3,660,995,000 + special revenue/enterprise 2,356,596,100 = 6,017,591,100 in FY2026) ties to Schedule 2's TOTAL 6,017,402,200 after the (188,900) duplicated transfers. In FY2014 the "Total Budget" 1,812,431,500 equals Schedule 3 NET BUDGETARY FUNDS.

**Cross-book overlap** (`overlap_check.csv`): 716 series compared, 279 differ by >0.5%. Pattern: a fiscal year's budget in its **own** book is the adopted budget; the same year's "Budget" column in **later** books is the amended/revised budget (the books describe mid-year amendments; later books agree with each other). GSD General Fund 10101: FY2024 1,490,780,400 (FY2024 book) vs 1,636,150,900 (FY2025 and FY2026 books); FY2023 1,285,568,900 vs 1,412,542,900; FY2022 1,135,078,000 vs 1,199,851,800; FY2021 1,056,008,000 vs 1,044,979,600 (amended down); FY2019 969,874,000 vs 975,615,900 (FY2020 book) vs 995,325,000 (FY2021 book). Actuals agree across books (FY2016 actual: FY2019 vs FY2020 book) except where a book re-states a fund (small). Pick one basis for growth analysis: *adopted* (own-year column, `book_fy == fiscal_year`) or *final amended* (latest later book), never a mix.

**Spot checks**: `spot_check.py` samples 5 rows each from Schedule 3 detail, Schedule 3 totals, Schedule 2 and Schedule 1, plus the Total Budget and combined tax rate of all 12 books, and confirms the printed amount and label words appear on the cited page: 32 of 32 pass. I also read the printed pages for FY2026 10101 GSD General 1,773,793,200, Fire 238,750,800, Property Taxes 1,101,019,400, Schedule 2 001 Administrative GSD 440,120,900, FY2014 002 Metropolitan Council 1,773,000 and FY2021 Schedule 2 rows by eye against the CSVs.

## Caveats for a spending-growth analysis

1. **Gross vs net of transfers.** Schedule 3 and Schedule 2 totals are gross (footnote: "Gross total dollar amounts include duplications due to interfund transfers"). The ordinance "Total Budget" is net of "Duplicated by Interfund Transfers" (12.1M in FY2014, 75.0M in FY2024, 0.2M in FY2026). FY2014 alone prints both GROSS and NET BUDGETARY FUNDS in Schedule 3.
2. **Six tax-supported funds vs all funds.** Headline totals cover the six budgetary funds (GSD General, GSD Debt, Schools General Purpose, Schools Debt, USD General, USD Debt). Schedule 3's special revenue section (and Schedule 2's Special Revenue / Enterprise columns) add ~2.0–2.6B of grants, hotel taxes, water & sewer, internal service funds, component units, etc.; internal service funds (ITS 51137, Fleet 51154, Treasury, employee benefit trusts 52xxx, MNPS self-insurance 55xxx) are charges to other departments and double count against departmental budgets.
3. **Pension and benefits sit in 001 Administrative**, not in departments: County/Teacher/Police-Fire/Civil Service retirement matches, health and life insurance match, IOD, benefit adjustments, pay-plan improvements (e.g. 01101315 "PayPlan Improvements" 11–16M), plus subsidies (WeGo/MTA 77M in FY2026, Hospital Authority 60.7M, Metro Action Commission 12.4M, Correctional Healthcare 31.7M, Forensic Medical Examiner, Barnes Housing Trust, Property Tax Relief) and judgments/contingencies. Departmental lines are salaries/operations only. 001's business-unit detail is in `schedule3_lines.csv` (row_type `bu`) for both GSD and USD funds.
4. **MNPS is one line** (fund 35131 General Purpose + 25104 Schools Debt Service in Schedule 3; department 080 in Schedule 2). Schedule 2 classifies the schools general purpose fund as *Special Revenue* in the FY2014–FY2016 books and as *Budgetary GSD Funds* from FY2019 on (same money, different column). MNPS FTEs are printed only in some books (FY2014: 9,303.50 inside the budgetary FTE total; FY2020–FY2025: 8,805–9,201 in GROSS FTEs; 0 in FY2015/16, FY2019, FY2026/27), so total-FTE series are not comparable across books — use the departmental FTEs and treat MNPS separately.
5. **GSD/USD split.** Police, Fire, Public Works/NDOT and 001 have both GSD and USD general-fund lines. The FY2026 USD/GSD study (Raftelis) moved USD fire services into the GSD: USD Fire 108.1M → 0 and GSD Fire 104.7M → 238.8M between FY2025 and FY2026; USD General fell from 188.4M to 67.7M, the USD tax rate from 0.332 to 0.032 and the GSD rate rose from 2.922 to 2.782 after reappraisal (combined 3.254 → 2.814). Analyse Fire (and NDOT, Police) as GSD + USD.
6. **Department changes** (see crosswalk): 042 Public Works → Nashville Department of Transportation and Multimodal Infrastructure (FY2022 book); 091 ECC → Department of Emergency Communications; 052 Community Oversight Board (FY2020–FY2024) → 054 Community Review Board (FY2024 budget on); 053 Office of Homeless Services created FY2024; 036 Soil and Water Conservation zeroed FY2019 and dropped; 014 ITS has only a small/intermittent GSD general-fund line (FY2014–FY2016, FY2019, FY2024 books) and is otherwise an internal service fund (Schedule 2 'Enterprise Funds' column); 070 Community Education Commission GSD line FY2019–FY2023; 072 Waste Services split out as a special-revenue department in the FY2026 book (previously inside Public Works/NDOT plus 001 "GSD Waste Services Transfers"); 062 State Fair Board → Board of Fair Commissioners; 071 Music City Center → Convention Center Authority; Water and Sewer is an enterprise fund (Schedule 2 only). Department codes are stable; names are not.
7. **Basis changes.** FY2014 book combined Transportation Licensing into Public Works for all years; the FY2021 book inserted "Cash & Fund Balance Restoration" lines (46.4M GSD, 7.2M USD) inside the general funds that are not departments; FY2021 (COVID) budget columns in Schedule 1 carry un-itemised reserve amounts; FY2024 ordinance fund totals include 75M of interfund transfers; FY2026/FY2027 ordinance tables are on an appropriations-incl.-reserves basis (see headline reconciliation). Prior-year "Budget" columns are amended budgets (see overlap check).
8. **Actuals** are modified-accrual year-end actuals printed in whole dollars; totals are computed from unrounded figures (hence the $2–$5 "rounding(book)" items). Actual-year revenues in Schedule 1 (e.g. FY2026 book GSD General FY2024 "Transfers Out" 177,595,800) include one-off transfers that distort function totals.
9. **Tax rates** are per $100 of assessed value; 2017, 2021 and 2025 are reappraisal years (certified rate reset). FY2015/FY2016 books print the combined rate rounded to $4.52 (components sum to 4.516); the FY2024 book's table header reads "2023 Rate 2023 Rate" (values are the FY2024 rates, unchanged from FY2023).
10. **FY2027 is a recommended (not adopted) budget**; its FY2026 "Budget" column already differs from the FY2026 adopted book (GSD General 1,804,636,300 vs 1,773,793,200).

## Coverage (which fiscal years have what)

- Actuals by department (Schedule 3): FY2011 (FY2014 book), FY2012 (FY2015), FY2013 (FY2016), FY2016 (FY2019), FY2017 (FY2020), FY2018 (FY2021), FY2019 (FY2022), FY2020 (FY2023), FY2021 (FY2024), FY2022 (FY2025), FY2023 (FY2026), FY2024 (FY2027). **No department-level actuals for FY2014 and FY2015** (they would be in the missing FY2017/FY2018 books). Schedule 1 adds fund-level actuals for FY2010 (FY2014 book) and FY2014/FY2015 (FY2019 book) — fund totals only.
- Budgets by department: FY2012–FY2016 (FY2014–FY2016 books), FY2017 and FY2018 only as amended prior-year columns (FY2019/FY2020 books; no adopted-year book), FY2019–FY2026 adopted (own-year books) plus amended versions in later books, FY2027 recommended.
- Schedule 2 (budget year by fund type): FY2014, FY2015, FY2016, FY2019–FY2026, FY2027 recommended.

## Re-running

`zsh "scripts/budget/run_all.sh"` (python3 with PyMuPDF 1.26). Drop `Budget_FY2017.pdf` / `Budget_FY2018.pdf` into `raw/budget/`, fill their page ranges in `scripts/budget/common.py` (`BOOKS[2017]`, `BOOKS[2018]`; find pages with `pdf_text.py <pdf> search "SCHEDULE 3"`), and re-run; the validation logs will show whether the layouts parse cleanly.
