Property Management Solutions
← 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#),
  NOT work_orders.actual_cost 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. Paid status flips **automatically on successful bill**.

  [w] → [1] Manage work orders
      Columns show #Exp and Exp$ (linked lines)
      X = list expenses on selected WO
      N = add expense for this WO (returns to WO list)
      K = cancel empty WO only (zero expense rows — T070)
      A = add WO (property + unit pickers; category ENUM)
  [w] → [2] Manage expenses  (or N from WO list)
      List default = pending on open jobs (hides pure status echo lag)
      Filter: pending · processed · all recent
      Expense status = line lock after bill — not a second owner settlement
      Edit category/amount only while status = pending
      Soft-cancel pending OK; paid locked
  [w] → [6] WOs missing expenses  (focus list)
  [w] → [3] Complete WO  (status = completed)
  [w] → [4] Bill owner
      Posts expense (−) to owner ledger
      Auto: WO → paid and pending expenses → paid
      Requires YES; fails if zero linked expenses
      This IS the recovery step (deducted on owner statement vs rent)
  [w] → [7] Reverse WO bill (T070 double-entry)
      Reason + YES → clear owner ledger for WO
      Soft-void invoiced|paid expenses → cancelled
      WO → completed (re-add pending lines then re-bill if needed)
      Never hard-delete billed expenses or WOs that have expenses
  [w] → [e] View status exceptions (only if integrity errors)
      Logged + dashboard + Mark ticket on crit — not a flip-status menu
  Do not use a separate “mark paid” operator step.

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.