Property Management Solutions
← All docs

How to run reports

HOW TO RUN REPORTS — PMS
========================
Updated: 2026-07-19

OWNER STATEMENTS (PRIMARY)
--------------------------
Menu:  [s] Statements & reports  →  [o] Owner statements hub

Packages (same generator for all kinds):
  · Monthly     YYYY-MM     operations close
  · Quarterly   YYYY-Qn     family office records
  · YTD         YTD / YYYY-YTD   Jan 1 → today (or Dec 31 if prior year)
  · Annual      YYYY        full calendar year · tax / family office
  · Custom range (CLI only) YYYY-MM YYYY-MM

Hub keys:
  [1] Browse list / summary for current period
  [2] View one owner on screen
  [3] Generate / refresh this period (idempotent)
  [4] Export paths (PDF/CSV for email · CPA)
  [5] Enter period (YYYY-MM · YYYY-Qn · YYYY · YTD)
  [m] This calendar month
  [t] Year to date (set period)
  [T] Generate YTD package now
  [p] Last completed quarter
  [y] Last calendar year (tax package)
  [Y] Current calendar year (full year package)
  [G] Generate quarterly (prompt year + Q1–4)
  [A] Generate annual (prompt year)
  [j] Owner portfolio job sheet (props · units · WOs)

CLI:
  bin/run owner-statements-generate 2026-07
  bin/run owner-statements-generate 2026-Q2
  bin/run owner-statements-generate YTD
  bin/run owner-statements-generate 2026-YTD
  bin/run owner-statements-generate 2025
  bin/run owner-statements-generate 2025-01 2025-06
  bin/run ops-owner-statements
  bin/run ops-owner-statements YTD
  bin/run owner-job-sheet 1

Output folders:
  reports/owner_statements/YYYY-MM/
  reports/owner_statements/YYYY-Qn/
  reports/owner_statements/YYYY-YTD/
  reports/owner_statements/YYYY/
    owner_{Name}_{period}.pdf   ← attach for family office / CPA
    owner_{Name}_{period}.csv
    owner_{Name}_{period}.md
    SUMMARY_{period}.pdf
    MANIFEST.txt

Content (all kinds — kitchen-table order):
  · Period activity from owner ledger (not trust cash balance)
  · Human period label · $ amounts with thousands separators (PDF/MD)
  · Signs: rent always +; expenses & mgmt fees always − (normalized even if old rows wrong)
  · Net = income + charges + fees + other (charges/fees negative)
  · 1 Summary → 2 By property → 3 Vacancy loss (memo) → rollups → line detail
  · Vacancy loss = opportunity cost while unit had no active lease (asking rent pro-rata)
    — NOT a ledger charge; does not change Net
  · Letterhead from [y] System → [L] PMO letterhead
  · Annual / YTD: not a tax form or 1099 substitute
  · If raw ledger signs still wrong: bin/run ledger-backfill (expense signs)

Owner portfolio job sheet [j]:
  · Bill-to owner contact · all properties · all units · open/recent WOs
  · Optional save under reports/portfolio/

PDF (Linux/macOS):
  pandoc + xelatex or pdflatex
  macOS (pull + review on MacBook):
    brew install pandoc && brew install --cask basictex
    eval "$(/usr/libexec/path_helper)"   # PATH: /Library/TeX/texbin
    sudo /Library/TeX/texbin/tlmgr update --self
    sudo /Library/TeX/texbin/tlmgr install collection-fontsrecommended \
      fancyhdr xcolor booktabs longtable setspace hyperref
    bin/run owner-statements-generate YTD
    open reports/owner_statements/$(date +%Y)-YTD/*.pdf
  Generator auto-adds /Library/TeX/texbin + Homebrew pandoc to PATH when missing.
  Headless Linux: generate OK; open PDFs on a desktop after git pull.

TENANT REPORTS
--------------
Menu [s]:
  [1] Monthly tenant rent statements
  [2] Tenant full ledger
  [3] All tenants rent summary (CSV)

DASHBOARDS
----------
Menu [d]:
  [1] Tenant dashboard
  [2] General portfolio dashboard
  [3] Inventory stats
  [4] Portfolio map — owner/unit directory + property job sheet

PORTFOLIO MAP (ownership / who lives where)
------------------------------------------
Menu:  [d] Dashboards  →  [4] Portfolio map
CLI:   bin/run portfolio-map
       bin/run portfolio-map directory
       bin/run portfolio-map directory owner=1
       bin/run portfolio-map directory property=2
       bin/run portfolio-map directory vacant
       bin/run portfolio-map job 2
       bin/run portfolio-map export

  [1] Full portfolio directory (owner → property → unit → tenant)
  [2] Directory filtered by owner  → shows owner list, then enter OID
  [3] Directory filtered by property → shows property list, then enter PID
  [4] Vacant doors only (still shows owner); empty = clear “no vacant” message
  [5] Property job sheet — bill-to owner, unit roster, open/recent WOs
      (yard work / property-level WO: who pays)
  [e] Export last directory view as CSV → reports/portfolio/

Ownership model (binding for ops):
  · One owner_id per property = bill-to for that row’s units and WOs
  · Unit = managed door; property = economic control for that owner
  · Same street address may appear on N properties when owners differ
    (condo / partial complex). Differentiate by apartment/unit number
    in address or description. See docs/wiki-Workflows.txt §1.

Troubleshooting pickers:
  · Lists must appear before the ID prompt. If a list is missing, upgrade
    portfolio_map.sh (picker bug: do not capture picker stdout with $()).

RENT / AR VIEWS
---------------
Menu [r] Rent & collections:
  [1] Leases + invoice/payment status
  [2] Run monthly rent invoicing (creates INV- for month)
  [3] Collect rent (also posts owner ledger)
  [4] AR exceptions / reverse payment (soft-void + ledger clear)
  [5] Bill work order to owner
  [6] AR aging detail report

Menu [s] Statements & reports also has AR aging at [6]
  (same report — convenient from either hub).

Requires migration 1.20 (payments.status) for [4] reverse workflow
and for posted-only payment sums on aging/exceptions.

AR AGING DETAIL REPORT
----------------------
Menu:  [r]→[6]  or  [s]→[6]
CLI:   bin/run ar-aging

Shows only overdue rent invoices (balance_owed > 0 and due_date < today).
On-screen columns (~80-col TUI): Tenant, Property, Unit, Due, Age, Owed, Bkt.
  · Unit = unit number only (property holds address)
  · Ordered by property, unit, then age (property subtotals group cleanly)
  · Orig / Paid totals on footer (posted payments only for Paid)
  · Bucket rollups: 0-30 / 31-60 / 61-90 / 90+ (amount owed)

Purpose: prioritize collection on oldest balances by property.
Reversed payments are excluded (status=posted only).
If the report errors with unknown column status → run migrations:
  ./migrations/migrate.sh up

AR EXCEPTIONS LIST ([r]→[4])
----------------------------
Main row: #, ID, Invoice, Tenant, Amount, Posted, Bal, Status (~80 cols).
Flags (OVERPAID, MULTI_PAY, …) print on the next indented line.
Payment drill-down: STATUS is posted|reversed; LEDGER is Y|N (do not swap).

OPERATOR CHECKLIST
------------------
Monthly close:
  1. [r]→[2]  Bill rent for calendar month
  2. [r]→[3]  Collect payments
  3. [w]      Expenses, complete WOs, bill owners
  4. [s]→[o]  Generate monthly owner statements → export PDFs

Quarterly (family office):
  [s]→[o]→[Q] or set period YYYY-Qn → [3] Generate

Annual (tax support):
  [s]→[o]→[A] or [y] last year → [3] Generate
  Attach per-owner PDF + CSV to CPA packet

See also: docs/workflows-finance.txt · docs/qa-regression-framework.md