From 51745193da2a8595991bbe553e1aad59cb0152b2 Mon Sep 17 00:00:00 2001 From: isaacclad Date: Sun, 7 Jun 2026 12:16:25 +0000 Subject: [PATCH] Fix events import payload decoding and programme link remapping. Decode JSON-string payloads from the platform export so event content, covers, and programme references import correctly. Co-authored-by: Cursor --- app/Console/Commands/ImportEventsCommand.php | 37 ++++++++- tests/Feature/ImportEventsCommandTest.php | 82 ++++++++++++++++++++ 2 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 tests/Feature/ImportEventsCommandTest.php diff --git a/app/Console/Commands/ImportEventsCommand.php b/app/Console/Commands/ImportEventsCommand.php index ce36f5d..df9c8d5 100644 --- a/app/Console/Commands/ImportEventsCommand.php +++ b/app/Console/Commands/ImportEventsCommand.php @@ -61,6 +61,9 @@ class ImportEventsCommand extends Command foreach ($payload['qr_codes'] ?? [] as $row) { $this->importCode($row, $commit); } + if ($commit) { + $this->remapAllProgrammeLinks(); + } foreach ($payload['qr_event_registrations'] ?? [] as $row) { $this->importRegistration($row, $commit); } @@ -127,17 +130,24 @@ class ImportEventsCommand extends Command 'user_id', ])->all(); $attrs['user_id'] = $user->id; + $attrs = $this->normalizeJsonAttributes($attrs, ['payload']); if ($commit) { $code = QrCode::updateOrCreate(['short_code' => $shortCode], $attrs); $this->codeMap[$platformId] = $code->id; - $this->remapProgrammeLinks($code); $this->copyCodeAssets($code); } else { $this->codeMap[$platformId] = $platformId; } } + private function remapAllProgrammeLinks(): void + { + QrCode::query() + ->where('type', QrCode::TYPE_EVENT) + ->each(fn (QrCode $code) => $this->remapProgrammeLinks($code)); + } + private function remapProgrammeLinks(QrCode $code): void { if ($code->type !== QrCode::TYPE_EVENT) { @@ -151,7 +161,30 @@ class ImportEventsCommand extends Command } $content['programme_qr_id'] = $this->codeMap[$programmeId]; - $code->update(['content' => $content]); + $payload = $code->payload ?? []; + $payload['content'] = $content; + $code->update(['payload' => $payload]); + } + + /** + * @param array $attrs + * @param list $keys + * @return array + */ + private function normalizeJsonAttributes(array $attrs, array $keys): array + { + foreach ($keys as $key) { + if (! isset($attrs[$key]) || ! is_string($attrs[$key])) { + continue; + } + + $decoded = json_decode($attrs[$key], true); + if (is_array($decoded)) { + $attrs[$key] = $decoded; + } + } + + return $attrs; } /** @param array $row */ diff --git a/tests/Feature/ImportEventsCommandTest.php b/tests/Feature/ImportEventsCommandTest.php new file mode 100644 index 0000000..6bb83c8 --- /dev/null +++ b/tests/Feature/ImportEventsCommandTest.php @@ -0,0 +1,82 @@ +create(['public_id' => 'usr_events_owner']); + + $payload = [ + 'qr_wallets' => [], + 'qr_codes' => [ + [ + 'platform_id' => 10, + 'owner_public_id' => $owner->public_id, + 'owner_email' => $owner->email, + 'short_code' => 'demo-programme', + 'type' => QrCode::TYPE_ITINERARY, + 'label' => 'Demo Programme', + 'payload' => json_encode(['content' => ['title' => 'Demo Programme'], 'style' => []]), + 'is_active' => true, + 'scans_total' => 0, + 'created_at' => now()->toDateTimeString(), + 'updated_at' => now()->toDateTimeString(), + 'destination_updated_at' => now()->toDateTimeString(), + ], + [ + 'platform_id' => 11, + 'owner_public_id' => $owner->public_id, + 'owner_email' => $owner->email, + 'short_code' => 'demo-event', + 'type' => QrCode::TYPE_EVENT, + 'label' => 'Demo Event', + 'payload' => json_encode([ + 'content' => ['name' => 'Demo Event', 'programme_qr_id' => 10], + 'style' => [], + ]), + 'is_active' => true, + 'scans_total' => 0, + 'created_at' => now()->toDateTimeString(), + 'updated_at' => now()->toDateTimeString(), + 'destination_updated_at' => now()->toDateTimeString(), + ], + ], + 'qr_event_registrations' => [], + 'qr_scan_events' => [], + 'qr_transactions' => [], + ]; + + $exportPath = storage_path('framework/testing/events-import.json'); + if (! is_dir(dirname($exportPath))) { + mkdir(dirname($exportPath), 0777, true); + } + file_put_contents($exportPath, json_encode($payload)); + + Artisan::call('events:import', [ + 'file' => $exportPath, + '--commit' => true, + ]); + + $event = QrCode::where('short_code', 'demo-event')->first(); + $programme = QrCode::where('short_code', 'demo-programme')->first(); + + $this->assertNotNull($event); + $this->assertNotNull($programme); + $this->assertIsArray($event->payload); + $this->assertSame('Demo Event', $event->content()['name'] ?? null); + $this->assertSame($programme->id, $event->content()['programme_qr_id'] ?? null); + } +}