Gray nodes are Firestore collections (same as Data Tables). Green nodes are ops actions — click one to jump to What code writes.
resident + stay and marks the applicant
converted.
Happy path down the center. Side columns: deny/waitlist exits, inventory, email log, support tickets.
Each green action above links to a row here.
| Action | Code | Tables |
|---|---|---|
| Apply | Typeform / import | applicants |
| Approve | POST /api/applications/:id/approve |
applicants · email_events |
| Move to waitlist | POST /api/applications/:id/move-to-waitlist |
waitlist_entries · applicants |
| Deny / Spam | POST …/deny|spam |
applicants — terminal |
| Calendly sync | calendlyWebhook / syncCalendlyInterviews |
interviews |
| Interview accept | POST /api/interviews/:id/decision |
interviews · applicants · email_events — no stay |
| Interview deny | same decision endpoint | interviews · applicants — terminal |
| 1st month’s rent | Outside repo (brownstone.live/reserve · PayPal) |
residents · stays · charges · payments · payment_allocations · applicants |
| Daily rent job | generateRentChargesDaily (06:00 PT) |
charges only |
| 2nd / future months’ rent | Payments UI / API | payments · payment_allocations · charge balances |
| Move-out | POST /api/beds/:podId/process-move-out |
stays · charges · beds · residents (if now) |
| Support import | Spreadsheet import (offline path) | support_tickets |
Same set as the Data Tables tab, plus interviews. Links = foreign keys / common joins.
| Collection | Role | Links to |
|---|---|---|
properties |
Houses | — |
beds |
Inventory units | properties via property_id |
bed_property_assignments |
Bed ↔ house over time | beds · properties |
applicants |
Funnel people | properties (desired_property_id) · residents (converted_resident_id) |
waitlist_entries |
Per-property queue | properties · optional applicants / residents |
interviews |
Calendly / manual calls | optional applicants · optional residents |
residents |
Billing / occupancy party | optional applicants · optional interviews (interview_id / interview_ids) |
stays |
Open-ended bed terms | residents · beds · properties |
charges |
Invoices / periods | stays · residents · optional properties |
payments |
Cash in | residents · optional properties |
payment_allocations |
Payment → charge | payments · charges |
email_events |
Outbound send log | optional applicants · residents · properties · stays · charges |
support_tickets |
Maintenance / ops tickets | properties · optional residents · beds · stays |
Things the lifecycle implies, but this admin repo does not implement (or only partially).
| Gap | What’s missing | |
|---|---|---|
| 1 | In-admin conversion | After interview accept, admin only sends the reserve link. Creating resident + stay + first charge/payment lives outside this repo (PayPal / 1st month’s rent). |
| 2 | Waitlist → bed | Marking a waitlist row “converted” does not create a resident, stay, charges, or bed assignment. Offer → 1st month’s rent is still a manual handoff. |
| 3 | Stay creation job | No scheduler creates stays. The daily job only writes new monthly charges for existing active stays. |
| 4 | Email delivery truth | email_events records SendGrid accept, not inbox delivery. Bounces / opens need a SendGrid Event Webhook that is not wired here. |
| 5 | Interviews in Data Tables | interviews is live product data but not on the Data Tables whitelist — only the Interviews UI / API. |
| 6 | Unified status model | Interview accept writes accepted; funnel/types mostly track approved / converted; waitlisted lands in “other.” No single status vocabulary across surfaces. |