Levandor CRM - Debugging Log

Purpose

Past bugs, their root causes, and resolutions for the Levandor CRM project.

Kanban DnD Cursor Offset (2026-03-09)

Symptom: Dragging kanban cards offset from cursor, invalid drops.

Root cause (3 compounding issues):

  1. CSS.Transform.toString(transform) includes scaleX(1) scaleY(1) causing visual offset
  2. Droppable ref on <ScrollArea> (Radix) - ref goes to Root but content scrolls in nested Viewport
  3. Original card visible during drag (opacity-60) alongside DragOverlay

Fix:

  1. Use CSS.Translate.toString(transform) instead
  2. Put ref on plain <div> wrapper around ScrollArea
  3. Set opacity: 0 on sortable wrapper when isDragging

Day Planner Uncancel Not Working (2026-03-09)

Symptom: Could cancel blocks but couldn’t restore them. Root cause: Toolbar always showed Play/Check/Cancel regardless of status. No restore action existed. Fix: When CANCELLED or DONE, replace with Restore button (Undo2 icon) → sets status=PLANNED, clears actual_start/actual_end.

CI TypeScript Build Failures (2026-03-09)

Symptom: tsc -b in CI failed with 14 errors, local tsc --noEmit passed.

Root cause: tsc -b (project build mode) stricter about cross-project type resolution:

  1. packages/shared missing @types/react devDependency
  2. Supabase .then() destructuring → implicit any under noImplicitAny
  3. Map constructor without generics → Map<unknown, unknown>
  4. Stale code referencing removed columns (is_closed, description)

Fix: Add @types/react to shared, use await instead of .then(), add Map generics, fix stale refs.

Lesson: Always verify with cd web && npx tsc -b before pushing.

pnpm Lockfile Out of Sync (2026-03-09)

Symptom: CI --frozen-lockfile failed. Root cause: Lockfile changes from adding workspaces weren’t committed. Fix: Commit the lockfile.

Billingo Vendor Bill Sync - Null Fields (2026-03-11)

Symptom: Vendor bills synced from Billingo API had null vendor_name, total_gross, spending_date.

Root cause: Wrong assumptions about API response structure:

Code assumedAPI actually returns
spending.namespending.partner?.name
spending.gross_pricespending.total_gross
spending.spending_datespending.fulfillment_date
spending.payment_statusspending.paid_at (date, derive status)

Fix chain (5 edge function deployments):

  1. v3: Corrected BillingoSpending interface + field mappings + deriveStatus()
  2. v4: Disabled JWT for testing → 157/163 bills created correctly
  3. DB: total_gross INTEGER → NUMERIC (API returns decimals)
  4. DB: Added VENDOR_BILL to budget_transaction_source_check constraint
  5. DB: Filter out zero-amount bills before budget transaction creation
  6. v5: Re-enabled JWT, removed debug code → production

Result: 163/163 vendor bills, 100% field population, zero nulls.

Lesson: Always inspect actual API responses with debug logging before writing TypeScript interfaces.