From 72cc6ff0b7ed4fc4ec3dc2be41e0d6e7b03cb665 Mon Sep 17 00:00:00 2001 From: myrmidex Date: Thu, 19 Mar 2026 21:01:56 +0100 Subject: [PATCH] 1 - Expose UUIDs in API responses and update frontend types --- app/Http/Controllers/BucketController.php | 8 ++++---- app/Http/Requests/StoreStreamRequest.php | 4 ++-- app/Http/Requests/UpdateStreamRequest.php | 4 ++-- app/Http/Resources/BucketResource.php | 2 +- app/Http/Resources/DrawResource.php | 4 ++-- app/Http/Resources/InflowResource.php | 4 ++-- app/Http/Resources/OutflowResource.php | 6 +++--- app/Http/Resources/ScenarioResource.php | 2 +- app/Http/Resources/StreamResource.php | 4 ++-- app/Repositories/StreamRepository.php | 24 +++++++++++++++++------ resources/js/pages/Scenarios/Index.tsx | 2 +- resources/js/pages/Scenarios/Show.tsx | 10 +++++----- 12 files changed, 43 insertions(+), 31 deletions(-) diff --git a/app/Http/Controllers/BucketController.php b/app/Http/Controllers/BucketController.php index f577329..65fd87f 100644 --- a/app/Http/Controllers/BucketController.php +++ b/app/Http/Controllers/BucketController.php @@ -19,7 +19,7 @@ public function index(Scenario $scenario): JsonResponse ->get() ->map(function ($bucket) { return [ - 'id' => $bucket->id, + 'id' => $bucket->uuid, 'name' => $bucket->name, 'priority' => $bucket->priority, 'sort_order' => $bucket->sort_order, @@ -136,12 +136,12 @@ public function updatePriorities(Request $request, Scenario $scenario): JsonResp { $validated = $request->validate([ 'bucket_priorities' => 'required|array', - 'bucket_priorities.*.id' => 'required|exists:buckets,id', + 'bucket_priorities.*.id' => 'required|exists:buckets,uuid', 'bucket_priorities.*.priority' => 'required|integer|min:1', ]); foreach ($validated['bucket_priorities'] as $bucketData) { - $bucket = Bucket::find($bucketData['id']); + $bucket = Bucket::where('uuid', $bucketData['id'])->first(); if ($bucket && $bucket->scenario_id === $scenario->id) { $bucket->update([ 'priority' => $bucketData['priority'], @@ -161,7 +161,7 @@ public function updatePriorities(Request $request, Scenario $scenario): JsonResp private function formatBucketResponse(Bucket $bucket): array { return [ - 'id' => $bucket->id, + 'id' => $bucket->uuid, 'name' => $bucket->name, 'priority' => $bucket->priority, 'sort_order' => $bucket->sort_order, diff --git a/app/Http/Requests/StoreStreamRequest.php b/app/Http/Requests/StoreStreamRequest.php index 177847b..62af8e6 100644 --- a/app/Http/Requests/StoreStreamRequest.php +++ b/app/Http/Requests/StoreStreamRequest.php @@ -41,7 +41,7 @@ public function rules(): array ], 'start_date' => ['required', 'date', 'date_format:Y-m-d'], 'end_date' => ['nullable', 'date', 'date_format:Y-m-d', 'after_or_equal:start_date'], - 'bucket_id' => ['nullable', 'exists:buckets,id'], + 'bucket_id' => ['nullable', 'exists:buckets,uuid'], 'description' => ['nullable', 'string', 'max:1000'], ]; } @@ -67,7 +67,7 @@ public function withValidator($validator): void $scenario = $this->route('scenario'); $bucketBelongsToScenario = $scenario->buckets() - ->where('id', $this->bucket_id) + ->where('uuid', $this->bucket_id) ->exists(); if (! $bucketBelongsToScenario) { diff --git a/app/Http/Requests/UpdateStreamRequest.php b/app/Http/Requests/UpdateStreamRequest.php index 7f346b4..13615dc 100644 --- a/app/Http/Requests/UpdateStreamRequest.php +++ b/app/Http/Requests/UpdateStreamRequest.php @@ -34,7 +34,7 @@ public function rules(): array ], 'start_date' => ['required', 'date', 'date_format:Y-m-d'], 'end_date' => ['nullable', 'date', 'date_format:Y-m-d', 'after_or_equal:start_date'], - 'bucket_id' => ['nullable', 'exists:buckets,id'], + 'bucket_id' => ['nullable', 'exists:buckets,uuid'], 'description' => ['nullable', 'string', 'max:1000'], 'is_active' => ['boolean'], ]; @@ -61,7 +61,7 @@ public function withValidator($validator): void // Validate that the bucket belongs to the stream's scenario if ($this->bucket_id) { $bucketBelongsToScenario = $stream->scenario->buckets() - ->where('id', $this->bucket_id) + ->where('uuid', $this->bucket_id) ->exists(); if (! $bucketBelongsToScenario) { diff --git a/app/Http/Resources/BucketResource.php b/app/Http/Resources/BucketResource.php index b9c79b3..1545180 100644 --- a/app/Http/Resources/BucketResource.php +++ b/app/Http/Resources/BucketResource.php @@ -10,7 +10,7 @@ class BucketResource extends JsonResource public function toArray(Request $request): array { return [ - 'id' => $this->id, + 'id' => $this->uuid, 'name' => $this->name, 'priority' => $this->priority, 'sort_order' => $this->sort_order, diff --git a/app/Http/Resources/DrawResource.php b/app/Http/Resources/DrawResource.php index 1b9ead3..07c6c1b 100644 --- a/app/Http/Resources/DrawResource.php +++ b/app/Http/Resources/DrawResource.php @@ -10,8 +10,8 @@ class DrawResource extends JsonResource public function toArray(Request $request): array { return [ - 'id' => $this->id, - 'bucket_id' => $this->bucket_id, + 'id' => $this->uuid, + 'bucket_id' => $this->bucket?->uuid, 'amount' => $this->amount_currency, 'formatted_amount' => $this->formatted_amount, 'date' => $this->date->format('Y-m-d'), diff --git a/app/Http/Resources/InflowResource.php b/app/Http/Resources/InflowResource.php index c0e3097..0e98dee 100644 --- a/app/Http/Resources/InflowResource.php +++ b/app/Http/Resources/InflowResource.php @@ -10,8 +10,8 @@ class InflowResource extends JsonResource public function toArray(Request $request): array { return [ - 'id' => $this->id, - 'stream_id' => $this->stream_id, + 'id' => $this->uuid, + 'stream_id' => $this->stream?->uuid, 'amount' => $this->amount_currency, 'formatted_amount' => $this->formatted_amount, 'date' => $this->date->format('Y-m-d'), diff --git a/app/Http/Resources/OutflowResource.php b/app/Http/Resources/OutflowResource.php index 142d6d8..9ea77c6 100644 --- a/app/Http/Resources/OutflowResource.php +++ b/app/Http/Resources/OutflowResource.php @@ -10,9 +10,9 @@ class OutflowResource extends JsonResource public function toArray(Request $request): array { return [ - 'id' => $this->id, - 'stream_id' => $this->stream_id, - 'bucket_id' => $this->bucket_id, + 'id' => $this->uuid, + 'stream_id' => $this->stream?->uuid, + 'bucket_id' => $this->bucket?->uuid, 'amount' => $this->amount_currency, 'formatted_amount' => $this->formatted_amount, 'date' => $this->date->format('Y-m-d'), diff --git a/app/Http/Resources/ScenarioResource.php b/app/Http/Resources/ScenarioResource.php index 563dba6..2d4b227 100644 --- a/app/Http/Resources/ScenarioResource.php +++ b/app/Http/Resources/ScenarioResource.php @@ -10,7 +10,7 @@ class ScenarioResource extends JsonResource public function toArray(Request $request): array { return [ - 'id' => $this->id, + 'id' => $this->uuid, 'name' => $this->name, 'description' => $this->description, 'created_at' => $this->created_at, diff --git a/app/Http/Resources/StreamResource.php b/app/Http/Resources/StreamResource.php index 664a5e5..d2c4096 100644 --- a/app/Http/Resources/StreamResource.php +++ b/app/Http/Resources/StreamResource.php @@ -10,7 +10,7 @@ class StreamResource extends JsonResource public function toArray(Request $request): array { return [ - 'id' => $this->id, + 'id' => $this->uuid, 'name' => $this->name, 'type' => $this->type, 'type_label' => $this->getTypeLabel(), @@ -19,7 +19,7 @@ public function toArray(Request $request): array 'frequency_label' => $this->getFrequencyLabel(), 'start_date' => $this->start_date->format('Y-m-d'), 'end_date' => $this->end_date?->format('Y-m-d'), - 'bucket_id' => $this->bucket_id, + 'bucket_id' => $this->bucket?->uuid, 'bucket_name' => $this->bucket?->name, 'description' => $this->description, 'is_active' => $this->is_active, diff --git a/app/Repositories/StreamRepository.php b/app/Repositories/StreamRepository.php index 649cebe..9f406eb 100644 --- a/app/Repositories/StreamRepository.php +++ b/app/Repositories/StreamRepository.php @@ -2,6 +2,7 @@ namespace App\Repositories; +use App\Models\Bucket; use App\Models\Scenario; use App\Models\Stream; use Illuminate\Support\Collection; @@ -11,7 +12,7 @@ class StreamRepository public function getForScenario(Scenario $scenario): Collection { return $scenario->streams() - ->with('bucket:id,name') + ->with('bucket:id,uuid,name') ->orderBy('type') ->orderBy('name') ->get(); @@ -19,11 +20,15 @@ public function getForScenario(Scenario $scenario): Collection public function create(Scenario $scenario, array $data): Stream { + $this->resolveBucketId($data); + return $scenario->streams()->create($data); } public function update(Stream $stream, array $data): Stream { + $this->resolveBucketId($data); + $stream->update($data); return $stream->fresh('bucket'); @@ -46,17 +51,24 @@ public function toggleActive(Stream $stream): Stream /** * Check if a bucket belongs to the scenario */ - public function bucketBelongsToScenario(Scenario $scenario, ?int $bucketId): bool + public function bucketBelongsToScenario(Scenario $scenario, ?string $bucketUuid): bool { - if (! $bucketId) { + if (! $bucketUuid) { return true; } return $scenario->buckets() - ->where('id', $bucketId) + ->where('uuid', $bucketUuid) ->exists(); } + private function resolveBucketId(array &$data): void + { + if (! empty($data['bucket_id'])) { + $data['bucket_id'] = Bucket::where('uuid', $data['bucket_id'])->value('id'); + } + } + /** * Get streams grouped by type */ @@ -64,12 +76,12 @@ public function getGroupedByType(Scenario $scenario): array { return [ 'income' => $scenario->streams() - ->with('bucket:id,name') + ->with('bucket:id,uuid,name') ->byType(Stream::TYPE_INCOME) ->orderBy('name') ->get(), 'expense' => $scenario->streams() - ->with('bucket:id,name') + ->with('bucket:id,uuid,name') ->byType(Stream::TYPE_EXPENSE) ->orderBy('name') ->get(), diff --git a/resources/js/pages/Scenarios/Index.tsx b/resources/js/pages/Scenarios/Index.tsx index 855f7ba..b5c1098 100644 --- a/resources/js/pages/Scenarios/Index.tsx +++ b/resources/js/pages/Scenarios/Index.tsx @@ -2,7 +2,7 @@ import { Head, router } from '@inertiajs/react'; import React, { useState } from 'react'; interface Scenario { - id: number; + id: string; name: string; created_at: string; updated_at: string; diff --git a/resources/js/pages/Scenarios/Show.tsx b/resources/js/pages/Scenarios/Show.tsx index 38b6f59..a04977e 100644 --- a/resources/js/pages/Scenarios/Show.tsx +++ b/resources/js/pages/Scenarios/Show.tsx @@ -2,14 +2,14 @@ import { Head, Link, router } from '@inertiajs/react'; import { useState } from 'react'; interface Scenario { - id: number; + id: string; name: string; created_at: string; updated_at: string; } interface Bucket { - id: number; + id: string; name: string; priority: number; sort_order: number; @@ -23,7 +23,7 @@ interface Bucket { } interface Stream { - id: number; + id: string; name: string; type: 'income' | 'expense'; type_label: string; @@ -32,7 +32,7 @@ interface Stream { frequency_label: string; start_date: string; end_date: string | null; - bucket_id: number | null; + bucket_id: string | null; bucket_name: string | null; description: string | null; is_active: boolean; @@ -140,7 +140,7 @@ export default function Show({ scenario, buckets, streams = { data: [] }, stream } }; - const handlePriorityChange = async (bucketId: number, direction: 'up' | 'down') => { + const handlePriorityChange = async (bucketId: string, direction: 'up' | 'down') => { const bucket = buckets.data.find(b => b.id === bucketId); if (!bucket) return;