From 39b1b806d99bfedd9ef8a0675c170989896c1651 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20St=C3=B6ckel?= Date: Sat, 17 Oct 2026 18:02:45 +0200 Subject: [PATCH] :fire: remove deprecated DepartureResource fields --- API_CHANGELOG.md | 4 +- app/Http/Resources/DepartureResource.php | 36 +------------ .../Stationboard/DepartureEntry.vue | 4 +- .../pages/Stationboard/Stationboard.vue | 22 ++++---- resources/types/Api.gen.ts | 48 ----------------- resources/types/Departure.ts | 25 --------- .../components/Checkin/CheckinInterface.vue | 10 ++-- .../components/Checkin/StationBoardEntry.vue | 4 +- resources/vue/components/CheckinLineRun.vue | 14 ++--- resources/vue/components/Stationboard.vue | 50 +++++++++-------- storage/api-docs/api-docs.json | 54 ------------------- 11 files changed, 57 insertions(+), 214 deletions(-) diff --git a/API_CHANGELOG.md b/API_CHANGELOG.md index 77ab8610c0..99d922b9a4 100644 --- a/API_CHANGELOG.md +++ b/API_CHANGELOG.md @@ -15,7 +15,6 @@ Check back here regularly to stay ahead of removals. | Announced | What? | Safe until | PR | |------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------|---------------------------------------------------------------| -| 2026-04-01 | `DepartureResource.stop.*` is deprecated → use `DepartureResource.station` instead | 2026-09-30 | [#4663](https://github.com/Traewelling/traewelling/pull/4663) | | 2026-04-07 | `OperatorResource.id` is deprecated as integer: will become a UUID after 2026-09-30. prefer `uuid` instead while migration-period | 2026-09-30 | [#4676](https://github.com/Traewelling/traewelling/pull/4676) | | 2026-05-14 | `POST /api/v1/trains/checkin` 409 response: `message.status_id` and `message.lineName` are deprecated. Use `data.conflicts` (full `StatusResource` array) instead | 2026-10-31 | [#4677](https://github.com/Traewelling/traewelling/pull/4677) | | 2026-07-19 | `StopoverResource.id` is deprecated as station ID: it currently holds the station ID (not unique within a trip). Use `station` for station details. After the safe-until date `id` is repurposed to the unique stopover ID | 2026-11-30 | [#4959](https://github.com/Traewelling/traewelling/pull/4959) | @@ -34,7 +33,8 @@ Removed the following deprecated fields, announced in 2026-03 and 2026-04: - `DepartureResource.destination`: use `direction` instead - `DepartureResource.line.productName`: use `line.name` instead - `DepartureResource.provenance`, `remarks`, `origin`, `currentTripPosition`, `loadFactor` and `line.operator`: were always `null` -- `DepartureResource.stop.products`, `line.public` and `line.adminCode`: were always placeholder values +- `DepartureResource.line.public` and `line.adminCode`: were always placeholder values +- `DepartureResource.stop`: use `station` instead - `CheckinSuccessResource.points.additional` (`POST /trains/checkin`): was always `null` - `WebhookResource.clientId` (`/webhooks`): use `client.id` instead - `WebhookResource.userId` (`/webhooks`): use `user.id` instead diff --git a/app/Http/Resources/DepartureResource.php b/app/Http/Resources/DepartureResource.php index b23b09e710..0c7eeefff2 100644 --- a/app/Http/Resources/DepartureResource.php +++ b/app/Http/Resources/DepartureResource.php @@ -5,38 +5,15 @@ namespace App\Http\Resources; use App\Dto\Internal\Departure; -use App\Enum\StationIdentifierType; use Illuminate\Http\Resources\Json\JsonResource; use OpenApi\Attributes as OA; #[OA\Schema( title: 'Departure', description: 'A single departure at a station', - required: ['tripId', 'stop', 'when', 'plannedWhen', 'platform', 'plannedPlatform', 'direction', 'line', 'cancelled', 'station'], + required: ['tripId', 'when', 'plannedWhen', 'platform', 'plannedPlatform', 'direction', 'line', 'cancelled', 'station'], properties: [ new OA\Property(property: 'tripId', description: 'Unique trip identifier', type: 'string', example: '1|200513|0|81|6012023'), - new OA\Property( - property: 'stop', - description: 'The stop at which this departure occurs', - properties: [ - new OA\Property(property: 'type', type: 'string', example: 'stop', deprecated: true), - new OA\Property(property: 'id', description: 'Träwelling internal station ID', type: 'integer', example: 5181, deprecated: true), - new OA\Property(property: 'name', type: 'string', example: 'Karlsruhe Hbf', deprecated: true), - new OA\Property( - property: 'location', - properties: [ - new OA\Property(property: 'type', type: 'string', example: 'location', deprecated: true), - new OA\Property(property: 'id', description: 'IBNR identifier (if available)', type: 'string', example: '8000191', nullable: true, deprecated: true), - new OA\Property(property: 'latitude', type: 'number', format: 'float', example: 48.993207, deprecated: true), - new OA\Property(property: 'longitude', type: 'number', format: 'float', example: 8.400977, deprecated: true), - ], - type: 'object', - deprecated: true, - ), - ], - type: 'object', - deprecated: true, - ), new OA\Property(property: 'when', description: 'Actual departure time (null if no realtime data)', type: 'string', format: 'date-time', example: '2023-01-06T13:49:00+01:00', nullable: true), new OA\Property(property: 'plannedWhen', description: 'Scheduled departure time', type: 'string', format: 'date-time', example: '2023-01-06T13:49:00+01:00'), new OA\Property(property: 'platform', description: 'Actual platform (null if no realtime data)', type: 'string', example: '3a', nullable: true), @@ -69,17 +46,6 @@ public function toArray($request): array { return [ 'tripId' => $this->resource->trip->tripId, - 'stop' => [ // @deprecated - remove after 2026-09-30, use station instead - 'type' => 'stop', - 'id' => $this->resource->station->id, - 'name' => $this->resource->station->name, - 'location' => [ - 'type' => 'location', - 'id' => $this->resource->station->getIdentifier(StationIdentifierType::DE_DB_IBNR)?->identifier, - 'latitude' => $this->resource->station->latitude, - 'longitude' => $this->resource->station->longitude, - ], - ], 'when' => $this->resource->realDeparture?->toIso8601String(), 'plannedWhen' => $this->resource->plannedDeparture->toIso8601String(), 'platform' => $this->resource->realPlatform, diff --git a/resources/tailwind-app/components/Stationboard/DepartureEntry.vue b/resources/tailwind-app/components/Stationboard/DepartureEntry.vue index effc16d5b8..8beb29523e 100644 --- a/resources/tailwind-app/components/Stationboard/DepartureEntry.vue +++ b/resources/tailwind-app/components/Stationboard/DepartureEntry.vue @@ -76,10 +76,10 @@ const platform = computed((): string | null => props.item.platform ?? props.item {{ item.direction }}

- {{ trans('stationboard.dep') }} {{ item.stop.name }} + {{ trans('stationboard.dep') }} {{ item.station.name }}

diff --git a/resources/tailwind-app/pages/Stationboard/Stationboard.vue b/resources/tailwind-app/pages/Stationboard/Stationboard.vue index 79815ed18d..54515cf434 100644 --- a/resources/tailwind-app/pages/Stationboard/Stationboard.vue +++ b/resources/tailwind-app/pages/Stationboard/Stationboard.vue @@ -100,20 +100,20 @@ function fetchNext(): void { fetchDepartures(next ?? fetchTime.value.plus({ minutes: 15 }).toISO() ?? undefined); } -function openLineRun(train: DepartureResource): void { +function openLineRun(departure: DepartureResource): void { router.push({ name: 'line-run', query: { - tripId: train.tripId, - lineName: train.line?.name ?? train.line?.fahrtNr, - startId: train.stop?.id, - plannedWhen: train.plannedWhen, - direction: train.direction, - originName: train.stop?.name, - product: train.line?.product ?? undefined, - mode: train.line?.mode ?? undefined, - color: train.line?.color ?? undefined, - textColor: train.line?.textColor ?? undefined, + tripId: departure.tripId, + lineName: departure.line?.name ?? departure.line?.fahrtNr, + startId: departure.station?.id, + plannedWhen: departure.plannedWhen, + direction: departure.direction, + originName: departure.station?.name, + product: departure.line?.product ?? undefined, + mode: departure.line?.mode ?? undefined, + color: departure.line?.color ?? undefined, + textColor: departure.line?.textColor ?? undefined, }, }); } diff --git a/resources/types/Api.gen.ts b/resources/types/Api.gen.ts index 1df57addd5..d88b68a6df 100644 --- a/resources/types/Api.gen.ts +++ b/resources/types/Api.gen.ts @@ -1302,54 +1302,6 @@ export interface DepartureResource { * @example "1|200513|0|81|6012023" */ tripId: string; - /** - * The stop at which this departure occurs - * @deprecated - */ - stop: { - /** - * @deprecated - * @example "stop" - */ - type?: string; - /** - * Träwelling internal station ID - * @deprecated - * @example 5181 - */ - id?: number; - /** - * @deprecated - * @example "Karlsruhe Hbf" - */ - name?: string; - /** @deprecated */ - location?: { - /** - * @deprecated - * @example "location" - */ - type?: string; - /** - * IBNR identifier (if available) - * @deprecated - * @example "8000191" - */ - id?: string | null; - /** - * @deprecated - * @format float - * @example 48.993207 - */ - latitude?: number; - /** - * @deprecated - * @format float - * @example 8.400977 - */ - longitude?: number; - }; - }; /** * Actual departure time (null if no realtime data) * @format date-time diff --git a/resources/types/Departure.ts b/resources/types/Departure.ts index 2bb375a070..73a55ee0cd 100644 --- a/resources/types/Departure.ts +++ b/resources/types/Departure.ts @@ -1,6 +1,5 @@ export type departureEntry = { tripId: string; - stop: HafasStop; when: string | null; plannedWhen: string | null; platform: string | null; @@ -31,27 +30,3 @@ export type HafasLine = { mode: any; // eslint-disable-line @typescript-eslint/no-explicit-any product: any; // eslint-disable-line @typescript-eslint/no-explicit-any }; - -export type HafasStop = { - type: string; - id: string; - name: string; - location: HafasLocation; - station: HafasStation; -}; -export type HafasStation = { - type: string; - id: string; - name: string; - location: HafasLocation; - products: { - [key: string]: boolean; - }; -}; - -export type HafasLocation = { - type: string; - id: string; - latitude: number; - longitude: number; -}; diff --git a/resources/vue/components/Checkin/CheckinInterface.vue b/resources/vue/components/Checkin/CheckinInterface.vue index 97a9bf1594..411a3e8b52 100644 --- a/resources/vue/components/Checkin/CheckinInterface.vue +++ b/resources/vue/components/Checkin/CheckinInterface.vue @@ -20,7 +20,7 @@ export default { type: Object, required: true, }, - selectedTrain: { + selectedDeparture: { type: Object, required: true, }, @@ -93,11 +93,11 @@ export default { visibility: this.visibility, business: this.business, ibnr: false, - tripId: this.selectedTrain.tripId, - lineName: this.selectedTrain.line.name ?? this.selectedTrain.line.fahrtNr, - start: this.selectedTrain.stop.id, + tripId: this.selectedDeparture.tripId, + lineName: this.selectedDeparture.line.name ?? this.selectedDeparture.line.fahrtNr, + start: this.selectedDeparture.station.id, destination: this.selectedDestination.id, - departure: DateTime.fromISO(this.selectedTrain.plannedWhen).setZone('UTC').toISO(), + departure: DateTime.fromISO(this.selectedDeparture.plannedWhen).setZone('UTC').toISO(), arrival: DateTime.fromISO(this.selectedDestination.arrivalPlanned).setZone('UTC').toISO(), force: this.collision, eventId: this.selectedEvent ? this.selectedEvent.id : null, diff --git a/resources/vue/components/Checkin/StationBoardEntry.vue b/resources/vue/components/Checkin/StationBoardEntry.vue index d16c0f5aae..6109b7b512 100644 --- a/resources/vue/components/Checkin/StationBoardEntry.vue +++ b/resources/vue/components/Checkin/StationBoardEntry.vue @@ -93,8 +93,8 @@ function normalizeLineName(name: string | null): string {
{{ item.direction }}
- - {{ trans('stationboard.dep') }} {{ item.stop.name }} + + {{ trans('stationboard.dep') }} {{ item.station.name }}
diff --git a/resources/vue/components/CheckinLineRun.vue b/resources/vue/components/CheckinLineRun.vue index 4e451b978a..55c4e64c95 100644 --- a/resources/vue/components/CheckinLineRun.vue +++ b/resources/vue/components/CheckinLineRun.vue @@ -7,7 +7,7 @@ export default { name: 'CheckinLineRun', components: { LoadingSkeletonRows }, props: { - selectedTrain: { + selectedDeparture: { type: Object, required: true, }, @@ -32,7 +32,7 @@ export default { }; }, watch: { - selectedTrain() { + selectedDeparture() { this.getLineRun(); }, }, @@ -48,9 +48,9 @@ export default { this.loading = true; const params = new URLSearchParams({ - hafasTripId: this.$props.selectedTrain.tripId, - lineName: this.$props.selectedTrain.line.name, - start: this.$props.selectedTrain.stop.id, + hafasTripId: this.$props.selectedDeparture.tripId, + lineName: this.$props.selectedDeparture.line.name, + start: this.$props.selectedDeparture.station.id, }); fetch(`/api/v1/trains/trip?${params.toString()}`) .then((response) => { @@ -61,9 +61,9 @@ export default { } response.json().then((result) => { this.lineRun = result.data; - const givenDeparture = DateTime.fromISO(this.$props.selectedTrain.plannedWhen); + const givenDeparture = DateTime.fromISO(this.$props.selectedDeparture.plannedWhen); const startIndex = this.lineRun.stopovers.findIndex((item) => { - if (Number(item.id) !== Number(this.$props.selectedTrain.stop.id)) { + if (Number(item.id) !== Number(this.$props.selectedDeparture.station.id)) { return false; } const dep = item.departurePlanned diff --git a/resources/vue/components/Stationboard.vue b/resources/vue/components/Stationboard.vue index a1543b29bb..4bc89a5d6b 100644 --- a/resources/vue/components/Stationboard.vue +++ b/resources/vue/components/Stationboard.vue @@ -28,9 +28,9 @@ export default { travelType: null, fetchTime: null, show: false, - selectedTrain: null, - selectedTrainBackgroundColor: null, - selectedTrainTextColor: null, + selectedDeparture: null, + selectedDepartureBackgroundColor: null, + selectedDepartureTextColor: null, selectedDestination: null, loading: false, stationName: null, @@ -49,7 +49,7 @@ export default { : DateTime.now().setZone('UTC'); }, showLineRun() { - return !!this.selectedTrain && !this.selectedDestination; + return !!this.selectedDeparture && !this.selectedDestination; }, showCheckinInterface() { return !!this.selectedDestination; @@ -81,19 +81,19 @@ export default { this.pushHistory(params); } }, - selectedTrain(value) { + selectedDeparture(value) { if (value !== null) { - this.selectedTrainBackgroundColor = this.selectedTrain?.line?.color || null; + this.selectedDepartureBackgroundColor = this.selectedDeparture?.line?.color || null; - if (this.selectedTrainBackgroundColor) { - this.selectedTrainTextColor = this.selectedTrain?.line?.textColor || null; + if (this.selectedDepartureBackgroundColor) { + this.selectedDepartureTextColor = this.selectedDeparture?.line?.textColor || null; } } }, }, mounted() { this.analyzeUrlParams().then(() => { - if (!this.selectedTrain) { + if (!this.selectedDeparture) { this.fetchData(); } }); @@ -108,14 +108,14 @@ export default { trans, showModal(selectedItem) { this.selectedDestination = null; - this.selectedTrain = selectedItem; + this.selectedDeparture = selectedItem; this.show = true; this.$refs.modal.show(); const data = new URLSearchParams({ tripId: selectedItem.tripId, lineName: selectedItem.line.name, - start: this.selectedTrain.stop.id, + start: this.selectedDeparture.station.id, departure: selectedItem.when, category: selectedItem.line.product, }); @@ -216,13 +216,13 @@ export default { if (!urlParams.has('destination')) { this.selectedDestination = null; } - this.selectedTrain = { + this.selectedDeparture = { tripId: urlParams.get('tripId'), line: { name: urlParams.get('lineName'), product: urlParams.get('category') || null, }, - stop: { + station: { id: urlParams.get('start'), }, plannedWhen: urlParams.get('departure'), @@ -252,7 +252,7 @@ export default { const urlParams = new URLSearchParams(window.location.search); if (urlParams.toString() !== this.pushState.toString()) { this.analyzeUrlParams().then(() => { - if (!this.selectedTrain) { + if (!this.selectedDeparture) { this.fetchData(); } }); @@ -275,7 +275,7 @@ export default { // triggering the selectedDestination watcher's history.back() this.suppressDestinationWatcher = true; this.selectedDestination = null; - this.selectedTrain = null; + this.selectedDeparture = null; this.fastCheckinIbnr = null; this.show = false; this.suppressDestinationWatcher = false; @@ -362,16 +362,20 @@ export default { -