Review: Appointment booking and calendar

review-1795-2026-07-06 Review

review needs-refinement

Verdict: NEEDS_REFINEMENT

Board item #1795 — #15 Appointment booking and calendar
Labels: type:feature,arch:rails,story:registration,sprint:5 | Points: 3
Forgejo: ldraney/intelligentstaffingsystems#15 (open)

Template Completeness

  • [x] Type — Feature
  • [x] Lineage — Depends on #8 (Lead model). Sprint 5.
  • [x] Repo — ldraney/intelligentstaffingsystems
  • [x] User Story — present
  • [x] Context — present, references US-1.3 and related docs
  • [x] File Targets — present (but incomplete, see below)
  • [x] Feature Flag — none
  • [x] Acceptance Criteria — present (5 items)
  • [x] Test Expectations — present
  • [x] Constraints — present
  • [x] Checklist — present
  • [x] Related — present
All required template sections are present.

Traceability

  • [x] story:registration label — Epic 1 (US-1.2–1.4), Role: Visitor/Lead
  • [x] story note verified — found in project-iss user-stories section (key: registration, backing: "Epic 1 (US-1.2–1.4)")
  • [x] arch:rails label — Rails application layer
  • [ ] arch note MISSING — no arch-rails note found in pal-e-docs. However, arch:rails is a categorical technology label applied to ~15 board items, not a specific architecture decision. [SCOPE] Create architecture note arch-rails for the Rails component, or reclassify arch:rails as a categorical label that does not require a backing note.
  • [x] Forgejo issue — #15, open

File Targets

Files to create (listed in issue):
  • [x] app/models/appointment.rb — verified: does not exist yet. architecture.md ER diagram defines Appointment with uuid id PK, uuid lead_id FK, datetime scheduled_at, string status, text notes.
  • [x] db/migrate/xxx_create_appointments.rb — verified: no appointments migration exists yet. Schema has no appointments table.
  • [x] app/controllers/appointments_controller.rb — verified: does not exist yet. security.md Controller Role Map expects AppointmentsController to skip auth.
  • [x] app/views/appointments/new.html.erb — verified: does not exist yet.
Files that should be modified (MISSING from issue):
  • [ ] config/routes.rb — ISSUE: not listed. Currently has a placeholder get "booking", to: "leads#booking" (line 7). Must be updated to add appointment resources and remove/replace the placeholder route.
  • [ ] app/controllers/leads_controller.rb — ISSUE: not listed. Has placeholder booking action (line 23) and redirects to booking_path after registration (line 16). Both need updating.
  • [ ] app/views/leads/booking.html.erb — ISSUE: not listed. Placeholder file ("Appointment booking is coming soon") that should be removed when the real implementation lands.
  • [ ] test/models/appointment_test.rb — ISSUE: test file not listed in File Targets, though Test Expectations mention model tests.
  • [ ] test/controllers/appointments_controller_test.rb — ISSUE: test file not listed in File Targets, though Test Expectations mention controller tests.
  • [ ] test/fixtures/appointments.yml — ISSUE: fixture file not listed.

Repo Placement

OK. Issue filed on ldraney/intelligentstaffingsystems, fix is in the same repo. Single-repo change.

Dependencies

  • #8 Lead model (board item #1788) — in validation column (near-done). Lead model exists with all fields. The lead_id FK on Appointment depends on this. Dependency satisfied.
  • #16 Postmark email (board item #1796) — in backlog. AC #4 says "Email triggered after booking (depends on #16)" but #16 has not started. This creates an unresolvable cross-dependency within the ticket scope. The booking ticket should not include email triggering as an acceptance criterion — it should defer to #16.
  • No blocking items in in_progress.

Acceptance Criteria

  • AC1: "After registration form, user is redirected to booking page" — testable, controller test can verify redirect ✓
  • AC2: "Appointment record created with scheduled_at and status" — testable, model + controller tests ✓
  • AC3: "Confirmation shown after booking" — testable, integration test ✓
  • AC4: "Email triggered after booking (depends on #16)" — NOT testable in this ticket. #16 is in backlog. Must be deferred.
  • AC5: "Related docs updated in this PR (docs-in-PR rule)" — testable ✓
5 AC total (at the decomposition threshold) but one should be deferred, bringing effective AC to 4.

Blast Radius

  • Existing placeholder flow: Registration (LeadsController#create) redirects to booking_path which serves a placeholder page. The agent must update this redirect and remove the placeholder without breaking the registration flow.
  • Routes: Adding appointment resources changes route helpers. No other controllers reference booking/appointment routes currently.
  • Unresolved architectural decision: docs/user-stories.md Open Question #1 explicitly says "Calendly embed vs custom booking — decided at this ticket; write the decision back." The issue body says "MVP can use Calendly embed if custom scheduling is too complex" but the architecture.md ER diagram assumes a custom Appointment model. This ambiguity must be resolved before work starts — the agent needs a clear directive, not a runtime judgment call.
  • Security surface: docs/security.md already documents AppointmentsController as skipping auth, status as a closed enum, and defensive scheduled_at parsing. These are good guardrails for the agent.

Decomposition Assessment

4 files to create + 3-6 files to modify = 7-10 files total, all in one repo. 4 effective AC (after deferring email). Estimated agent work: ~4 minutes. No decomposition needed — fits in a single agent pass once scope gaps are fixed.

Recommendations

  • [BODY] Add modification file targets: config/routes.rb (add appointment resources, remove/replace placeholder booking route), app/controllers/leads_controller.rb (update redirect and remove placeholder booking action), app/views/leads/booking.html.erb (remove placeholder). Add test targets: test/models/appointment_test.rb, test/controllers/appointments_controller_test.rb, test/fixtures/appointments.yml.
  • [BODY] Remove or defer AC #4 ("Email triggered after booking (depends on #16)"). #16 is in backlog — this ticket should stand alone. Email integration is #16's responsibility.
  • [BODY] Resolve the Calendly vs custom scheduling decision in the Context section. The architecture.md ER diagram assumes a custom Appointment model. If choosing custom scheduling (recommended, since the model is already designed), state it explicitly. Write the decision back to docs/user-stories.md Open Question #1 as part of the docs-in-PR rule.
  • [SCOPE] Create architecture note arch-rails for the Rails component, or adopt a convention that broad technology labels (arch:rails, arch:frontend, arch:docs) are categorical and do not require backing notes.