Skip to content

Projects & Project Detail

StatusShipped
LinearPIN-432 ↗ PIN-484 ↗
ModuleProjects ↗

The awarded-work hub. A project is created manually or by awarding a bid, then everything lives in the detail page's tab strip. The highest-value QA checks here are role gating (Budget confidentiality) and the tab-by-tab scope map — several tabs are intentional placeholders.

Prerequisites

  • Role: PM or higher for the main pass; an Assistant PM login specifically for the Budget-gating checks.
  • Test data: PDFs from docs-pdfs/ for the Documents tab.

1. Projects list

Projects in the nav (/projects). KPI band on top (Active / Total Projects / Total Value / Avg Compliance). Seven columns: PROJECT #, PROJECT NAME, ADDRESS, GC / CLIENT (one combined column), PM, STATUS, CONTRACT $ (Start Date and Floor hidden by default — toggle via the column-visibility control). One Status filter dropdown (In Setup / Active / On Hold / Complete / Archived) + debounced search.

2. Create a project — two paths

  • Manual: New Project (hidden without create permission) → full-page form. Required: Project Name; Project Number auto-generates if empty. Other fields: Status, Project Type, Project Manager (PM-category users only), Contract Value, dates, Address (Google Places autocomplete), Contracting Counterparty (GC) and Client (each with a + quick-add). Property Manager and Owner's Rep appear on the edit form only — absent on create is intended.

    PIN-524, fixed 2026-07-18 — creating with only a name used to fail with an HTTP 500 (db_error, an unwrapped projectManagerId: 0 foreign-key violation). Worth a quick regression check that it stays fixed; no longer requires the Project Manager workaround. - Via bid award: awarding a bid creates the project and redirects to the list with the new row transiently highlighted.

The Edit form also holds the Danger Zone → Delete project (permission-gated).

3. The tab strip — scope map

Deep-linkable via ?tab=; browser Back navigates between tabs. What each tab is, and where its dedicated walkthrough lives:

Tab What / where covered
Overview Read-only dashboard: KPIs, quick actions, map (only if the project has a location), activity feed, key issues, vendor compliance. Schedule card is a "Coming soon" placeholder.
Handoff Award handoff brief (permission-gated; flagged for September redesign).
Team Step 5 below.
Spec Sections CSI spec sections (feeds Submittals create form). Permission-gated — absent if the environment's permission seed is stale (bit the local stand 2026-07-08).
Budget Step 4 below — the confidentiality flagship.
Purchase Orders PO requests / issued POs (permission-gated).
Project Controls Nested Submittals + RFIsSubmittals, RFIs.
Change Orders Change Orders.
Billing Schedule of Values / billing.
Documents Step 6 below.
Drawings Project Drawings.
Field Nested Progress / Daily Logs / Punch List / Reports — Daily Logs.
Schedule / Closeout / Shares Under Construction placeholders — filing bugs against them wastes time.

4. Budget tab — confidentiality checks (PIN-432)

This is two-layer by design; test both:

  1. As Assistant PM: the Budget tab must be absent from the strip. Deep-link ?tab=budget directly → one warning toast "You don't have access to Budget" and a redirect to Overview.
  2. Backend zeroing: an Assistant PM still gets the cost-code list where needed (CO/PO creation), but with budgeted amounts zeroed. Zeros for APM are masking, not data loss.
  3. As PM+: five stat cards (Original Budget / CO Adjustments / Revised Budget / Committed / Remaining), a commitment progress bar, then divisions with cost-code tables. The VARIANCE column shows only for the exec tier (Owner/Exec/Sr.PM) — its absence for a plain PM is intended.
  4. Row click → cost-code drawer: PO history, Request PO, Mark Issued, vendor quote history (each permission-gated).

Empty state "No budget yet — Cost codes appear here once the awarded estimate is converted to a project." is valid for manually created projects.

The deep-link bounce occasionally shows the warning toast twice on a cold load — dedup gap, cosmetic.

5. Team tab

Three cards: Key Parties (read-only denormalized FKs: PM, GC, Client, Property Manager, Owner's Rep), Members (internal users — add/edit/delete, each gated), Organizations (external parties). Add Organization: pick an org (already-attached ones excluded from the list) + a role from the seeded catalog; compliance status shows as a colored chip.

6. Documents tab

Seven collapsible folders (Bid Documents, Drawings & Revisions, Specifications, Contracts & Exhibits, Proposal, RFIs & Correspondence, Reference & Support), each with a file count. Expand → Subfolder + Upload (drag-drop, max 200 MB). Per-file: Download, Move to folder dropdown, Remove (confirm modal). Upload a few docs-pdfs/ files, move one between folders, remove one.

Verification Checklist

  • Manual create with only a name succeeds; project number auto-generates
  • Property Manager / Owner's Rep fields appear on edit but not on create
  • Assistant PM: no Budget tab, deep-link bounces with a single toast, cost-code amounts read zero where visible
  • PM sees Budget without VARIANCE; Owner/Exec sees VARIANCE
  • Team: add/remove a member and an organization; duplicate org is not offered
  • Documents: upload / move between folders / remove all work with toasts
  • Schedule, Closeout, Shares show Under Construction (no dead crashes)
  • No console errors throughout

Known Issues / Current Gaps

  • SharePoint import/sync has shipped since this walkthrough was last verified — a sync button on the Bids/Projects list populates the Documents tab automatically for matching folders (see doc 02, Priority 10). Test it alongside plain manual upload/download, not instead of it.
  • ⚠ Most projects have no Google Place set — no map on Overview and no weather in Daily Logs; intended until the address backfill lands.
  • 🕐 Schedule, Closeout, Shares tabs are placeholders; Handoff is queued for a September redesign.

Updating this walkthrough

Run the full flow yourself end-to-end. If it passes, bump last_verified: in the frontmatter to today's date. If any step fails, fix the doc or the code in the same PR — drift is the enemy.