Skip to content

add VAA stand reservation plan payload validation and JSON schema - #1877

Open
MrAdder wants to merge 23 commits into
VATSIM-UK:vaa_event_stand_planningfrom
MrAdder:vaa-issue-1847
Open

add VAA stand reservation plan payload validation and JSON schema#1877
MrAdder wants to merge 23 commits into
VATSIM-UK:vaa_event_stand_planningfrom
MrAdder:vaa-issue-1847

Conversation

@MrAdder

@MrAdder MrAdder commented Apr 17, 2026

Copy link
Copy Markdown
Contributor

Defined the JSON schema for VAA stand plans and wrote the server side validation against it.
Wrote the public facing documentation that can be used to guide VAAs to make the JSON payloads

Closes #1847

MrAdder and others added 4 commits April 17, 2026 12:44
Introduce an endpoint to accept VAA stand reservation plan submissions. Adds StandReservationPlanController@store, a FormRequest (StoreStandReservationPlan) that restricts submissions to VAA users, and a comprehensive validation rule (StandReservationPlanPayload) which enforces strict JSON schema, Zulu timestamps, CID/airport/stand rules, and rejects overlapping reservations for the same stand. Registers the route POST /stand/reservation-plan, adds documentation (docs/guides/VaaStandReservationPlans.md) and links it from the StandAllocation guide, and includes controller tests to cover successful submission, authorization, overlap detection, and multi-airport validation. On success the API creates a plan with status=submitted and returns 201 with id and status.
Breaks the large invokable validation into smaller private methods for clarity and testability. Adds validateEventTimes, extractReservations, collectStandIntervals, validateReservationAndBuildInterval and resolveStandKey to parse/validate event times, extract reservations, build per-stand intervals and resolve stand keys. Changes reservations validation to return early when invalid, collects intervalsByStand and then validates overlaps. Preserves existing validation messages while improving structure and null/edge-case handling.
Rework validation control flow to avoid early returns and consolidate result construction. Introduces an $interval result that's only returned when stand, from and to are valid; resolveStandKey no longer returns immediately on errors but sets and returns a nullable stand key. event_airport(s) handling was simplified to build an airports array, validate each entry (reporting per-item errors) and check duplicates at the end. Tighten and harden parseZuluTime to more robustly validate and parse Zulu timestamps. Overall this improves error accumulation and readability of the validation logic.
Extract validation logic from the main rule into small private helper methods to improve readability and testability. Added validateSingleStandMode, validateReservationTimes, resolveStandKeyFromId, resolveStandKeyFromIdentifier, validateSingleEventAirport and validateMultipleEventAirports. These methods encapsulate existing checks for stand selection, Zulu time parsing and ordering, stand key resolution (by id or code+airport) and event_airport(s) normalization/validation. No validation messages or behaviour were changed; logic was reorganized and returned values made explicit.

Co-Authored-By: Copilot <198982749+Copilot@users.noreply.github.com>
@MrAdder
MrAdder marked this pull request as ready for review April 17, 2026 15:36

@CLC0609 CLC0609 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've had a brief look through and the schema and validation looks good.

Can we just focus this PR on that, and leave the controllers and API endpoints for another PR please?

@MrAdder

MrAdder commented Apr 17, 2026

Copy link
Copy Markdown
Contributor Author

Sure will have that sorted in a few

Delete the StandReservationPlan submission endpoint and related code: removes the controller (app/Http/Controllers/StandReservationPlanController.php), request validation (app/Http/Requests/Stand/StoreStandReservationPlan.php), and tests (tests/app/Http/Controllers/StandReservationPlanControllerTest.php). Also unregisters the POST stand/reservation-plan route in routes/api.php, removing the API for submitting stand reservation plans.

@CLC0609 CLC0609 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good, couple of nit picky things from me!

Comment thread app/Rules/Stand/StandReservationPlanPayload.php
Comment thread app/Rules/Stand/StandReservationPlanPayload.php Outdated
Comment thread app/Rules/Stand/StandReservationPlanPayload.php Outdated
Comment thread app/Rules/Stand/StandReservationPlanPayload.php
Comment thread docs/guides/StandAllocation.md Outdated
Comment thread docs/guides/VaaStandReservationPlans.md Outdated
Comment thread docs/guides/VaaStandReservationPlans.md Outdated
Comment thread docs/guides/VaaStandReservationPlans.md Outdated
MrAdder and others added 6 commits April 18, 2026 05:50
Co-authored-by: Coby Chapman <cobylc.121@gmail.com>
Co-authored-by: Coby Chapman <cobylc.121@gmail.com>
Co-authored-by: Coby Chapman <cobylc.121@gmail.com>
Co-authored-by: Coby Chapman <cobylc.121@gmail.com>
Co-authored-by: Coby Chapman <cobylc.121@gmail.com>
Tighten validation for stand reservation payloads: require stand_id to be a positive integer, restrict airport ICAO codes to UK prefixes (EG|EI) and update related error messages. Remove an unused isPositiveInteger helper and adjust airport normalization/validation logic. Update docs to clarify single vs multi-airport wording, event window requirements, and reservation rules. Add comprehensive unit tests covering valid/invalid UK ICAOs, overlapping reservations, out-of-window times, unknown fields, and negative stand IDs.
Comment thread docs/guides/VaaStandReservationPlans.md Outdated
@kristiankunc

Copy link
Copy Markdown
Contributor

Let's also create a JSON schema for the format - makes it much easier to catch errors right away, even with the end user

@MrAdder

MrAdder commented Apr 18, 2026

Copy link
Copy Markdown
Contributor Author

Sure will do that in a little bit after dinner

Add a JSON Schema for VAA stand reservation plans at docs/guides/schemas/vaa-stand-reservation-plan.schema.json and update the guide to reference it. The schema validates payload structure, field types, ISO 8601 Zulu timestamps, CID ranges, UK ICAO formats, and stand reference modes. The doc clarifies time formatting and lists server-side checks that JSON Schema cannot enforce (event_end > event_start, reservation timeto > timefrom, reservations within the event window, and no overlapping reservations for the same stand).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a JSON schema, server-side validation rule, and accompanying documentation/tests for VAA stand reservation plan submissions, aligning with issue #1847.

Changes:

  • Added StandReservationPlanPayload Laravel InvokableRule to validate stand reservation plan payloads (timestamps, airport scope, reservation windows, and overlap detection).
  • Added a Draft 2020-12 JSON Schema for VAA stand reservation plan submissions.
  • Added a public guide and unit tests covering key acceptance/rejection scenarios.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
app/Rules/Stand/StandReservationPlanPayload.php Implements payload validation (structure, time parsing, airport scope, reservation constraints, overlap checks).
tests/app/Rules/Stand/StandReservationPlanPayloadTest.php Adds unit tests for the new validation rule.
docs/guides/schemas/vaa-stand-reservation-plan.schema.json Defines the JSON schema for pre-validation of submissions.
docs/guides/VaaStandReservationPlans.md Public-facing guidance for constructing valid JSON payloads.
docs/guides/StandAllocation.md Adds a pointer to the new VAA reservation plan guide.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread app/Rules/Stand/StandReservationPlanPayload.php Outdated
Comment thread app/Rules/Stand/StandReservationPlanPayload.php Outdated
Comment thread docs/guides/VaaStandReservationPlans.md Outdated
Comment thread tests/app/Rules/Stand/StandReservationPlanPayloadTest.php
@MrAdder

MrAdder commented Apr 20, 2026 via email

Copy link
Copy Markdown
Contributor Author

@CLC0609
CLC0609 requested a review from kristiankunc April 23, 2026 18:46
MrAdder and others added 4 commits May 4, 2026 19:26
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Add a guard to StandReservationPlanPayload to ensure the resolved airport exists in the event's airports. If the airport is not found, the rule triggers a failure with "$itemPath.airport must be one of the event's airports." and returns null. Uses a strict in_array check to prevent invalid airport values.
Consolidate two separate validations into a single conditional: if the resolved airport is null or not in the event's airports, fail with an appropriate message chosen via a conditional expression. This reduces duplicated fail/return branches and clarifies the validation logic in StandReservationPlanPayload.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 8 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread app/Rules/Stand/StandReservationPlanPayload.php
Comment thread app/Rules/Stand/StandReservationPlanPayload.php
Comment thread app/Rules/Stand/StandReservationPlanPayload.php Outdated
Comment thread docs/guides/VaaStandReservationPlans.md Outdated
Comment thread docs/guides/schemas/vaa-stand-reservation-plan.schema.json
Comment thread tests/app/Rules/Stand/StandReservationPlanPayloadTest.php
Comment thread app/Rules/Stand/StandReservationPlanPayload.php
Comment thread app/Rules/Stand/StandReservationPlanPayload.php
MrAdder and others added 3 commits May 4, 2026 19:36
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Require reservations to be a non-empty list (using array_is_list) and update the validation message accordingly. Add an early return when event_airports is an empty array to avoid emitting reservation airport mismatch errors for invalid event_airports. Include tests for missing airport on multi-airport events, airport not in event_airports, ignoring airport-mismatch when event_airports is invalid/empty, and rejecting reservations that are not a list.
Rework conditional flow for airport resolution/validation in StandReservationPlanPayload: combine the event airports check with the airport normalization/validation block, move the successful return inside that block, and unify the final return to null. Preserves existing failure behavior (calls $fail when airport is missing or not one of the event's airports) while simplifying control flow and reducing early returns.
@sonarqubecloud

Copy link
Copy Markdown

MrAdder added 2 commits August 7, 2026 09:01
Refactors stand-airport resolution for reservation stand identifiers so invalid airport values are reported correctly instead of being treated as missing. Single-airport events still infer a missing reservation airport, while multi-airport events require it explicitly.

Also updates ICAO validation/error messaging to clearly require UK or Irish codes (`EG`/`EI`) with examples, and aligns docs/tests with the new behavior.
Simplifies stand reference generation and airport resolution by collapsing early returns into expression-based flow and extracting missing-airport inference into a dedicated helper. This keeps validation behavior consistent while making the control flow easier to follow, including explicit nulling when a provided airport is not in the event airport list.
@MrAdder MrAdder changed the title Add VAA stand reservation plan endpoint add VAA stand reservation plan payload validation and JSON schema Aug 7, 2026
Extend `StandReservationPlanPayloadTest` with negative cases for unparseable `event_start` and `event_end` values, including when one or both timestamps are invalid. This strengthens coverage around date parsing validation for stand reservation plan payloads.
@sonarqubecloud

sonarqubecloud Bot commented Aug 7, 2026

Copy link
Copy Markdown

@MrAdder
MrAdder requested a review from CLC0609 August 7, 2026 08:42
@MrAdder

MrAdder commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Sorry for the ReRequest @CLC0609 I been away and busy with Uni, resolved all issues that copilot brought up and what you both brought up on the issues

@MrAdder

MrAdder commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

The NavaidResourceTest::testItEditsPublishedHoldsWithMinimumLevelRestrictionMinimalData
failure is a pre-existing flaky test, unrelated to this PR.

Root cause — a range mismatch between the Hold factory and the form validation:

  • database/factories/Hold/HoldFactory.php:31 generates
    'outbound_leg_value' => $this->faker->randomFloat(1, 0.5, 100.5) — upper bound 100.5
  • app/Filament/Resources/NavaidResource/RelationManagers/HoldsRelationManager.php:81
    validates that field with ->maxValue(100)

This specific test builds a hold with Hold::factory()->make() and then calls the edit
action without passing outbound_leg_value, so the form prefills straight from the
factory. When faker rolls 100.1–100.5, the prefilled value breaches maxValue(100) and
Livewire reports an error on exactly the key in the failure output:
mountedTableActionsData.0.outbound_leg_value.

That's 5 failing values out of 1001 possible, so roughly a 0.5% failure rate per run
consistent with a single failure across 4089 tests, in the one test whose name
("MinimalData") indicates it doesn't override the field.

Not from this branch. git blame puts all three relevant lines in 2022:

Line Commit Date
HoldFactory.php:31 bd6246d8a 2022-12-11
HoldsRelationManager.php:81 bd6246d8a 2022-12-11
The failing test 029417f67 2022-08-13

This PR changes five files — app/Rules/Stand/StandReservationPlanPayload.php, its test,
docs/guides/schemas/vaa-stand-reservation-plan.schema.json, and two docs files. None are
in the Navaid/Hold/Filament path, and nothing here is reachable from that test.

A re-run should go green. The fix, whenever someone picks it up, is to align the factory
bound (randomFloat(1, 0.5, 100)) — I've deliberately left it out of this PR to keep the
scope to the schema and validation rule as requested. Will raise this as a separate issue.

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.

4 participants