create(); $package = Package::factory()->endcustomer()->create([ 'max_photos' => 10, ]); $event = Event::factory()->for($tenant)->create(); $eventPackage = EventPackage::create([ 'event_id' => $event->id, 'package_id' => $package->id, 'purchased_price' => $package->price, 'purchased_at' => now(), 'used_photos' => 8, 'used_guests' => 0, 'gallery_expires_at' => now()->addDays(7), ])->fresh(['package']); /** @var PackageUsageTracker $tracker */ $tracker = app(PackageUsageTracker::class); $tracker->recordPhotoUsage($eventPackage, 7, 1); EventFacade::assertDispatched(EventPackagePhotoThresholdReached::class); EventFacade::assertNotDispatched(EventPackagePhotoLimitReached::class); } public function test_dispatches_limit_event_when_reached(): void { EventFacade::fake([ EventPackagePhotoThresholdReached::class, EventPackagePhotoLimitReached::class, ]); $tenant = Tenant::factory()->create(); $package = Package::factory()->endcustomer()->create([ 'max_photos' => 2, 'max_guests' => null, ]); $event = Event::factory()->for($tenant)->create(); $eventPackage = EventPackage::create([ 'event_id' => $event->id, 'package_id' => $package->id, 'purchased_price' => $package->price, 'purchased_at' => now(), 'used_photos' => 2, 'used_guests' => 0, 'gallery_expires_at' => now()->addDays(7), ])->fresh(['package']); /** @var PackageUsageTracker $tracker */ $tracker = app(PackageUsageTracker::class); $tracker->recordPhotoUsage($eventPackage, 1, 1); EventFacade::assertDispatched(EventPackagePhotoLimitReached::class); } public function test_dispatches_guest_threshold_event_when_crossed(): void { EventFacade::fake([ EventPackageGuestThresholdReached::class, EventPackageGuestLimitReached::class, ]); $tenant = Tenant::factory()->create(); $package = Package::factory()->endcustomer()->create([ 'max_guests' => 10, ]); $event = Event::factory()->for($tenant)->create(); $eventPackage = EventPackage::create([ 'event_id' => $event->id, 'package_id' => $package->id, 'purchased_price' => $package->price, 'purchased_at' => now(), 'used_photos' => 0, 'used_guests' => 8, 'gallery_expires_at' => now()->addDays(7), ])->fresh(['package']); /** @var PackageUsageTracker $tracker */ $tracker = app(PackageUsageTracker::class); $tracker->recordGuestUsage($eventPackage, 7, 1); EventFacade::assertDispatched(EventPackageGuestThresholdReached::class); EventFacade::assertNotDispatched(EventPackageGuestLimitReached::class); } public function test_dispatches_guest_limit_event_when_reached(): void { EventFacade::fake([ EventPackageGuestThresholdReached::class, EventPackageGuestLimitReached::class, ]); $tenant = Tenant::factory()->create(); $package = Package::factory()->endcustomer()->create([ 'max_guests' => 2, ]); $event = Event::factory()->for($tenant)->create(); $eventPackage = EventPackage::create([ 'event_id' => $event->id, 'package_id' => $package->id, 'purchased_price' => $package->price, 'purchased_at' => now(), 'used_photos' => 0, 'used_guests' => 12, 'gallery_expires_at' => now()->addDays(7), ])->fresh(['package']); /** @var PackageUsageTracker $tracker */ $tracker = app(PackageUsageTracker::class); $tracker->recordGuestUsage($eventPackage, 11, 1); EventFacade::assertDispatched(EventPackageGuestLimitReached::class); } public function test_effective_limits_include_extras(): void { EventFacade::fake([ EventPackagePhotoLimitReached::class, ]); $tenant = Tenant::factory()->create(); $package = Package::factory()->endcustomer()->create([ 'max_photos' => 2, ]); $event = Event::factory()->for($tenant)->create(); $eventPackage = EventPackage::create([ 'event_id' => $event->id, 'package_id' => $package->id, 'purchased_price' => $package->price, 'purchased_at' => now(), 'used_photos' => 2, 'used_guests' => 0, 'gallery_expires_at' => now()->addDays(7), 'extra_photos' => 2, ])->fresh(['package']); /** @var PackageUsageTracker $tracker */ $tracker = app(PackageUsageTracker::class); // Base limit reached but extras still available; no limit event expected yet. $tracker->recordPhotoUsage($eventPackage, 1, 1); EventFacade::assertNotDispatched(EventPackagePhotoLimitReached::class); // Now consume extras and hit the effective limit. $eventPackage->used_photos = 4; $tracker->recordPhotoUsage($eventPackage, 3, 1); EventFacade::assertDispatched(EventPackagePhotoLimitReached::class); } }