# PlusROI review backlog (rian, 2026-07-12)

Rian's review of the soft-launched PlusROI tenant, with the triage verdict
and the agreed direction. **We must come back and address ALL of this.**
Not exhaustive — more will surface. Ordered by category, not priority.

## A. Import bugs — fix the importer + re-import (clean, source preserved)
1. **No contacts.** The importer jams each client's emails into a TEXT
   field (`client_profiles.contacts = "a@x | b@y"`) instead of making
   first-class Contact person-records + `cc_recipient` affiliations. Should
   be hundreds of contacts linked to clients. **VALID BUG.**
2. **Blank fields (e.g. AbodeZero's address).** Importer maps
   currency/terms/commission/credit-limit but SKIPS address + phone (and
   possibly others). **VALID BUG** — audit every sheet column → where it
   lands or a logged reason it's dropped.
3. **Project start date "missing."** Actually IMPORTED
   (`project_billing.start_date`) but NOT DISPLAYED. **UI gap, not data
   loss** — verify other "missing" fields are the same (imported-not-shown).
4. **Milestone vs recurring miscategorized + no amount (OA Region 6).**
   ROOT CAUSE: the recurrence model (`is_recurring`/`cycle_months`/
   `billing_timing`, alembic 0008) was added AFTER the importer; the
   importer was never updated to populate it — so every project defaults
   `is_recurring=false` and the Type→model + amount mapping is wrong. Map
   the sheet `Type` (Monthly/Quarterly/Yearly/Bi-Monthly → recurring +
   cycle + amount; Fixed/deposit → milestones). **VALID BUG, highest-value
   import fix.**

## B. Multi-tenant projects — the structural one (→ role model)
5. **Second Wind : General Maintenance exists in BOTH tenants.** Projects
   carry a hard `tenant_id`, so BW's (time) and PlusROI's (invoices) are two
   separate rows. WRONG: it's ONE real project, worked by BW, billed by
   PlusROI. **Fix = elevate the project to a tenant-agnostic, hub-owned
   anchor with `project_roles`** (end_client / operator / commission_owner /
   subcontractor / labour). A tenant SEES a project when its party has a
   role, and reads it through that role. No duplication. Decided (2026-07-12):
   do this WITH the hub build, not a flat re-import. See the role diagram in
   the conversation + `docs/design/` (to be written).

## C. Relationships — model already holds it; data comes with PM
6. The Second Wind / AISV / CFD / Tingang / Adi web. The engagement +
   project-role model can represent all of it. For BOOKKEEPING, payer +
   per-project commission is sufficient and correct (CFD's commission-on-
   PlusROI-not-AISV rule lives per-project). The RICH web (Paying≠End
   client, sub-sub-subcontract) is Airtable/PM data, NOT the books sheet —
   don't reconstruct it from sheet name-prefixes. Reserve an `end_client`
   link for the PM/Airtable import. **Don't over-build now.**

## D. Usability — the real next chunk (per-use-case)
7. The Danielle/Rob/Rian flows don't flow in the UI (backend proven via API,
   but screens are thin): e.g. Danielle can't filter projects to
   active+recurring+mid-month, invoice timing isn't a column, no obvious
   per-project "create invoice" button. **VALID.** Approach: one use case at
   a time — make Danielle's billing run genuinely smooth end-to-end first,
   then the next. Don't design all at once.

## E. Data-model simplifications confirmed
8. **Drop the time-log "operator" column.** With the role model a time
   entry needs only `project_id`; operator/client/commission are read off
   the project's roles, per tenant. `raw_operator` stays as provenance only.
   The model gets SIMPLER, not more complex.

## F. Invoices ↔ sprints/sets alignment (with PM)
9. Both invoices (books) and sets/sprints (PM) share the shape one /
   multiple-fixed / recurring. Link them LOOSELY and OPTIONALLY (nullable
   "this invoice covers this set") — never a hard 1:1. Both hang off the
   shared project.
