Review: Stripe ↔ DB data reconciliation: parent names, tournament status, orphan charges (v2)

review-1670-2026-06-30-v2 Review

review approved

Verdict: APPROVED

Re-review after refinement. Previous review (review-1670-2026-06-30) returned NEEDS_REFINEMENT with two findings. Both addressed.

Previous Findings Resolution

  • [x] [LABEL] story:WS-S12 → story:WS-S9 — FIXED. Board item labels updated. Issue body Related section now references story:WS-S9. Story aligns directly with ticket purpose: "As an admin, I want to track payment status per player so that I know who owes what."
  • [x] [SCOPE] arch-rails note missing — Acknowledged as platform-wide gap. The arch:rails label is used across multiple board items but no arch-rails note exists in pal-e-docs. Not blocking for this individual ticket; tracked as cross-cutting documentation debt.

Template Completeness

  • [x] Type — Feature
  • [x] Lineage — Standalone, discovered during manual audit
  • [x] Repo — ldraney/westside-basketball
  • [x] User Story — proper As/I want/So that format
  • [x] Context — detailed, 5 categories of data inconsistency documented with tables
  • [x] File Targets — 2 modify/create, 2 do-not-touch boundaries
  • [x] Feature Flag — none (appropriate for rake task)
  • [x] Acceptance Criteria — 5 items, all verifiable
  • [x] Test Expectations — present with run command
  • [x] Constraints — 5 constraints including idempotency and secret handling
  • [x] Checklist — present
  • [x] Related — present, references story:WS-S9
  • [x] Validation Queries — bonus section with concrete reproduction commands

Traceability

  • [x] story:WS-S9 label — "As an admin, I want to track payment status per player so that I know who owes what"
  • [x] story note verified — WS-S9 found in project-westside-basketball user-stories section under Admin (Marcus)
  • [x] arch:rails label — present on board item
  • [~] arch note MISSING — search_notes("arch-rails") returned empty. Platform-wide gap, not blocking. [INFO] Create architecture note arch-rails when addressing cross-cutting documentation debt.
  • [x] Forgejo issue — #131, open, valid

File Targets

  • [x] lib/tasks/stripe_reconciliation.rake — NEW file. Directory lib/tasks/ exists with 2 existing rake files (seed_tournament_attendance.rake, tournament_email.rake). Correct location for new rake task.
  • [x] app/models/player_tournament.rb — EXISTS (337 bytes). Model defines PAYMENT_STATUSES = %w[pending paid_stripe paid_cash paid_venmo waived]. The paid_stripe status is a valid enum value. Schema has amount_cents (integer, nullable) and payment_status (string, default "pending").
  • [x] Do-not-touch boundaries verified — app/views/admin/** and app/controllers/** correctly excluded.
  • [x] app/services/stripe_client.rb — EXISTS (7.8k). Provides Stripe API access patterns the rake task can reuse.

Repo Placement

OK — issue filed on ldraney/westside-basketball, all code changes are in the same repo. Single-repo ticket.

Dependencies

  • No blocking in_progress issues. In-progress items are phases (15, 14, 11) — none conflict.
  • Phase 14 (Billing Tiers & Contracts) is the parent phase and is in_progress — correct context.
  • Board item #1660 (missing env vars for Stripe) is in backlog. Not a hard blocker — existing Stripe integration (webhooks_controller.rb, stripe_client.rb) is working, confirming the key is available.
  • Upstream seed_tournament_attendance.rake (PR #125) already merged — creates the PlayerTournament records this task reconciles.
  • Todo items are iOS/app-store related, unrelated to this ticket.

Acceptance Criteria

  • 5 criteria, all testable by an agent.
  • AC #1 (rake task runs audit): Clear — run bin/rails stripe:reconcile and verify output.
  • AC #2 (markdown report): Clear — output covers payment gaps, orphan charges, data quirks.
  • AC #3 (idempotent): Clear — re-run produces same result without duplication.
  • AC #4 (orphan charge email matching): Clear — orphans with known parent emails are flagged.
  • AC #5 (exclude test charges): Clear — $1 test charges from Lucas filtered out.
  • Validation queries section provides concrete reproduction commands.

Blast Radius

  • Low blast radius. Creates 1 new rake task file, modifies no existing files structurally.
  • Data writes confined to player_tournaments.payment_status column updates (pending → paid_stripe).
  • No schema migrations, no controller changes, no view changes.
  • Existing StripeClient service provides reusable Stripe API patterns.
  • Admin dashboard display changes explicitly out of scope (separate ticket).

Decomposition Assessment

  • 2 file targets in 1 repo — under threshold.
  • 5 acceptance criteria — at threshold, not over.
  • Estimated agent work: <5 minutes. Single rake task creation, no schema changes, clear patterns from existing rake tasks and StripeClient.
  • No decomposition needed.

Recommendation

No action needed. Both previous findings resolved. Ticket is ready for implementation.
[INFO] The arch-rails note gap is tracked as platform-wide documentation debt and does not block this ticket.