← All docs
Workflows
PMS — WORKFLOWS
===============
Updated: 2026-07-19
Finance detail: docs/workflows-finance.txt
1. ONBOARDING ENTITIES
----------------------
[o] Owner → [p] Property → [u] Unit → [t] Tenant → [l] Lease
Check [v] vacant units before leasing.
Ownership model (operator guidance)
-----------------------------------
· One owner_id per property. That owner is the bill-to for rent fees and
work orders under that property (including property-level yard work).
· The unit is the managed door. The property row is the economic control
unit you manage for that owner — not necessarily a unique street parcel.
Same street address, different owners (condo / multi-owner complex)
· Allowed and preferred: N separate properties may share the same address.
· Differentiate in the address or description with the apartment/unit
number, e.g.:
55 Lucky Valley #11
55 Lucky Valley #12
or address = "55 Lucky Valley" + unit_number = "11" on a property that
has only that one managed unit.
· Put a short note on each property, e.g.:
"Parcel shared building; managed door #11 only — Owner Rosina"
· Do NOT put two owners' doors under one property — bill-to would be wrong.
· Common-area work you do not manage is not a billed PMS WO (or is
non-billable). Work one owner pays for stays on that owner's property.
Same owner, many doors at one building
· One property + many units (normal multi_family / apartment_complex).
True co-ownership of the same door's cash (50/50 siblings, trust splits)
· Prefer one bill-to (LLC or primary) and split outside the system, OR a future
ownership-share model — not duplicate address rows for the same cash flow.
See portfolio map: [d] → [4] (directory + property job sheet).
Find an owner's property / add a unit to a shell
-----------------------------------------------
1. [p] Properties — list shows Owner + Units (0 = shell, no units yet)
· Type / then owner name (or address) to filter
· Or sort 4=Owner / 5=Units
2. Select the row → detail shows Owner Name + Units on property
3. Note the PID, then [u] Units → A Add unit
· Picker lists PID · Address · Owner · Units (shells show 0)
· Enter that PID only (blank or q cancels)
4. Confirm under [p] that Units went from 0 → 1, or [d]→[4] directory
Tenant + lease (vacant unit) — operator path
--------------------------------------------
1. [v] Confirm unit is vacant (no current active lease)
2. [t] → A Add tenant
· First + last name required
· Email or phone required (at least one)
· Then open Leases to place them
3. [l] → A Add lease
· Pick tenant from list
· Pick available unit (same current-window rule as [v])
· Defaults: start = 1st of month · end ≈ +12 months
rent = unit base_monthly_rent · deposit = rent
· Status default active
4. Side effects (automatic)
· Unit status → occupied when lease is active and started
· Second active lease on same unit is refused
· Future-start lease: unit stays vacant until start_date
5. [r] → monthly invoicing once the start month is due
Turnover
--------
· Edit lease status to terminated (or delete with YES)
· Unit status → vacant when no current active lease remains
· Make-ready if needed ([u] unit status not-ready → vacant)
· New tenant [t] → new lease [l] on the free unit
2. MONTHLY RENT
---------------
[r] → [2] Monthly rent invoicing
Calendar month · INV-YYYYMM-#####
Issue/due days from PMO settings (default 1 / 5)
Preview count → type YES → safe re-run
[r] → [3] Collect rent
Records payment; posts rent_collected (+) and management_fee (−)
Warns if invoice already paid — do not double-enter
[r] → [4] AR exceptions / reverse pay
Lists OVERPAID / PAID_NO_PAYMENT / BALANCE_DRIFT invoices
[R] soft-void a payment (reason + YES) → clear owner ledger for that
payment_id → recompute invoice balance
[F] fix invoice status from posted payments only
Never hard-delete payment rows; regenerate owner statements after reverse
Needs migration 1.20 (payments.status / reverse columns)
[r] → [6] AR aging detail (also [s]→[6])
Overdue rent only · buckets 0-30/31-60/61-90/90+ · property subtotals
Late fee % from settings when payment after due date.
Collect prompts: [A]pply / [W]aive (default) / custom amount.
Cold-start: waive late (or set pay date = due) so go-live is not auto-punished.
Collected late fee → owner other_income (+); mgmt % on rent only.
3. WORK ORDER MONEY CYCLE
-------------------------
Critical: bill-to-owner charges SUM(expenses linked to WO#) = Exp$,
NOT work_orders.actual_cost / Est alone. Enter expense lines first.
Money recovery = Bill owner (ledger expense −), which nets against rent
on the owner package. There is NO separate “collect expense from owner”
cash step. After successful Bill + YES, face status = **charged**
(DB may still store paid|invoiced — same lock). Packages only READ the
ledger; they do not flip WO status.
Happy path (preferred):
[w] → [1] Manage work orders (primary ticket)
A = add WO (menu numbers for property/unit — not DB ids)
N = add cost lines (oneshot; q cancels) — blocked once face=charged
C = complete job (status only)
B = bill owner → summary [B]/[E]/[Q] → Type YES only on money step
After charged: more owner cost = new WO (A), not more lines on this ticket
L = view: active (default) → ready → missing → archive → all
X = expense table · K = cancel empty WO · S = search
Kitchen table vs drawer:
active = open work + charged still on the table
archive = charged after charge-month ended AND owner packages issued
(MANIFEST under reports/owner_statements/YYYY-MM or Qn)
Charged does NOT hide at Bill YES (avoids vanishing anxiety)
Other doors (optional):
[w] → [2] Manage expenses (cross-WO inbox; or N from WO list)
Pending default; processed = charged/cancelled
Edit/cancel only while pending; charged lines locked
[w] → [3] Complete WO shortcut (optional E/B after)
[w] → [4] Bill owner (same money path as B on ticket)
[w] → [5]/[6] Quick lists (ready / missing expenses)
[w] → [7] Reverse WO charge (T070 double-entry)
Reason + YES → clear ledger · soft-void charged expenses · WO → completed
Never hard-delete charged expenses or WOs that have expense rows
[w] → [e] Status exceptions (integrity only — not a flip menu)
Do not free-edit charged status. No separate “mark paid” menu.
4. OWNER STATEMENTS
-------------------
[s] → [o] Owner statements hub
Default period = current month
Generate → browse → export PDF
Letterhead: [y] → [L]
Regenerate anytime (idempotent).
5. SYSTEM / PMO
---------------
[y] → [5] Business parameters (fee %, invoice days)
[y] → [L] Letterhead
[y] → [4] Admin (inventory, telemetry, drift, SQL audit)
[y] → [6] Ledger backfill (historical payments / expense signs)
[y] → [Q] QA Lab (sandbox pmdb_qa only)
Seed [4] once · re-fight battles without wipe
Lease onboard [l]/[m] · AR reverse [v] · statement recon [t]
Rent [5–9 a c d] · WO [w] · season [s g]
Wipe [7] only when corrupt / DEFEAT will not clear
6. AUTHORIZED CODE
------------------
New script: add to manifest/scripts.tsv then bin/run <id>
New SQL: add to manifest/sql.tsv then bin/runsql / pms_runsql
bin/audit-sql shows remaining inline SQL.