seed(RoleSeeder::class); $this->org = Organisation::factory()->create(); $this->event = Event::factory()->create([ 'organisation_id' => $this->org->id, 'start_date' => CarbonImmutable::now()->subDay(), 'end_date' => CarbonImmutable::now()->addDays(30), ]); $this->stage = Stage::factory()->create(['event_id' => $this->event->id]); StageDay::query()->create(['stage_id' => $this->stage->id, 'event_id' => $this->event->id]); $artist = Artist::factory()->create(['organisation_id' => $this->org->id]); $this->engagement = ArtistEngagement::factory()->create([ 'artist_id' => $artist->id, 'event_id' => $this->event->id, 'booking_status' => ArtistEngagementStatus::Draft, 'fee_amount' => 1500, ]); $start = CarbonImmutable::now()->addDays(2)->setTime(20, 0); $this->perf = Performance::factory()->create([ 'engagement_id' => $this->engagement->id, 'event_id' => $this->event->id, 'stage_id' => $this->stage->id, 'lane' => 0, 'start_at' => $start, 'end_at' => $start->addHour(), 'version' => 0, ]); } public function test_performance_moved_carries_cascade_props(): void { $other = Performance::factory()->create([ 'engagement_id' => $this->engagement->id, 'event_id' => $this->event->id, 'stage_id' => $this->stage->id, 'lane' => 0, 'start_at' => CarbonImmutable::now()->addDays(2)->setTime(20, 30), 'end_at' => CarbonImmutable::now()->addDays(2)->setTime(21, 30), 'version' => 0, ]); $start = CarbonImmutable::now()->addDays(2)->setTime(20, 0); $this->app->make(LaneCascadeService::class)->move( performance: $this->perf, targetStage: $this->stage, start: $start, end: $start->addHour(), targetLane: 0, clientVersion: 0, ); $entry = Activity::query() ->where('event', 'moved') ->where('subject_id', $this->perf->id) ->latest('id') ->first(); $this->assertNotNull($entry); $props = $entry->properties->toArray(); $this->assertArrayHasKey('cascade_count', $props); $this->assertArrayHasKey('cascaded_ids', $props); $this->assertSame(1, $props['cascade_count']); $this->assertContains((string) $other->id, $props['cascaded_ids']); } public function test_status_changed_distinct_from_cancelled(): void { $service = $this->app->make(ArtistEngagementService::class); $service->transitionStatus($this->engagement, ArtistEngagementStatus::Requested); $this->assertTrue( Activity::query() ->where('event', 'status_changed') ->where('subject_id', $this->engagement->id) ->exists(), ); $this->assertFalse( Activity::query() ->where('event', 'cancelled') ->where('subject_id', $this->engagement->id) ->exists(), ); $eng2 = ArtistEngagement::factory()->create([ 'artist_id' => Artist::factory()->create(['organisation_id' => $this->org->id])->id, 'event_id' => $this->event->id, 'booking_status' => ArtistEngagementStatus::Confirmed, 'fee_amount' => 1000, ]); $service->cancel($eng2); $this->assertTrue( Activity::query() ->where('event', 'cancelled') ->where('subject_id', $eng2->id) ->exists(), ); } public function test_stage_day_added_emitted(): void { $sub = Event::factory()->create([ 'organisation_id' => $this->org->id, 'parent_event_id' => $this->event->id, ]); $this->app->make(StageDayService::class)->replaceDays( $this->stage, [$this->event->id, $sub->id], ); $this->assertTrue( Activity::query() ->where('event', 'day_added') ->where('subject_id', $this->stage->id) ->whereJsonContains('properties->event_id', $sub->id) ->exists(), ); } public function test_stage_reordered_emitted_on_event_subject(): void { $other = Stage::factory()->create(['event_id' => $this->event->id]); $this->app->make(StageService::class)->reorder($this->event, [$other->id, $this->stage->id]); $this->assertTrue( Activity::query() ->where('event', 'reordered') ->where('subject_id', $this->event->id) ->exists(), ); } }