Skip to content

feat(admin): public-ticket guest policy settings endpoints (Task 6.3)#36

Open
mpge wants to merge 2 commits intomainfrom
feat/admin-public-tickets-settings
Open

feat(admin): public-ticket guest policy settings endpoints (Task 6.3)#36
mpge wants to merge 2 commits intomainfrom
feat/admin-public-tickets-settings

Conversation

@mpge
Copy link
Copy Markdown
Member

@mpge mpge commented Apr 24, 2026

Summary

Adds `GET` + `PUT /escalated/api/admin/settings/public-tickets` so admins can switch the public-ticket guest-policy mode at runtime via the shared `Admin/Settings/PublicTickets.vue` page. Closes Plan Task 6.3 for the Spring greenfield host adapter.

Spring already had `SettingsService` + `EscalatedSettings` + repository from an earlier PR, so this is a pure controller-layer add — no migration or schema changes needed.

What's added

Three guest-policy keys under the `public_tickets` settings group:

  • `guest_policy_mode` ∈ `unassigned | guest_user | prompt_signup`
  • `guest_policy_user_id` — required when mode = `guest_user`
  • `guest_policy_signup_url_template` — optional when mode = `prompt_signup` (≤500 chars)

Handler semantics match the rest of the rollout (Symfony / .NET / Go):

  • Unknown mode values coerce to `unassigned` (never 500s on bad input)
  • Mode switch clears fields that don't apply to the new mode
  • Zero / negative / non-numeric user_id surfaces as JSON `null` on GET
  • Signup URL templates are trimmed + truncated to 500 chars

`PublicTicketsSettingsRequest` record uses `@JsonProperty` snake_case attributes so the wire format matches what the shared Vue page sends.

Test plan

  • CI: `./gradlew test` — 8 new MockMvc tests:
    • defaults-when-empty
    • `guest_user` + `prompt_signup` happy paths (with cross-mode cleanup)
    • unknown-mode coercion
    • 500-char truncation
    • zero user_id handling
    • mode-switch cleanup edge case
    • multi-write read-after-write consistency
  • Couldn't run `./gradlew test` locally (no Java toolchain on this box); relies on CI
  • Reviewer: sanity-check the `@JsonProperty` on record components pattern works with the project's Jackson version (standard Java 14+ record pattern; should be fine with Spring Boot 3's Jackson 2.15+, but worth a spot-check if this is the first record-based request DTO in the codebase)

Follow-ups

  • Phoenix still needs equivalent endpoints for Task 6.3 parity — similar lift to the Go port (Ecto schema + migration + service + controller).

Adds GET + PUT /escalated/api/admin/settings/public-tickets so admins
can switch the public-ticket guest-policy mode at runtime via the
shared Admin/Settings/PublicTickets.vue page. Closes Plan Task 6.3 for
the Spring greenfield host adapter.

Spring already had SettingsService + EscalatedSettings + repo from an
earlier PR, so this is a pure controller-layer add — no migration or
schema changes needed.

Three guest-policy keys back the policy (same shape as the Symfony,
.NET, and Go ports):
- guest_policy_mode ∈ { unassigned, guest_user, prompt_signup }
- guest_policy_user_id (required for guest_user)
- guest_policy_signup_url_template (optional for prompt_signup, ≤500
  chars)

All three are stored under the "public_tickets" settings group.
Handler semantics match the rest of the rollout:
- Unknown mode values coerce to "unassigned" (never 500s on bad input)
- Mode switch clears fields that don't apply to the new mode
- Zero/negative/non-numeric user_id surfaces as JSON null on GET
- Signup URL templates are trimmed + truncated to 500 chars

PublicTicketsSettingsRequest record uses @JsonProperty snake_case
attributes to match the wire format the shared Vue page sends.

8 MockMvc tests cover: defaults-when-empty, guest_user + prompt_signup
happy paths (with cross-mode cleanup), unknown-mode coercion, 500-char
truncation, zero user_id handling, mode-switch cleanup edge case, and
multi-write read-after-write consistency.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant