create(); $package = Package::factory()->reseller()->create([ 'max_events_per_year' => 10, ]); $tenantPackage = TenantPackage::factory() ->for($tenant) ->for($package) ->create([ 'used_events' => 6, ])->fresh(); /** @var TenantUsageTracker $tracker */ $tracker = app(TenantUsageTracker::class); $tracker->recordEventUsage($tenantPackage, 4, 2); EventFacade::assertDispatched(TenantPackageEventThresholdReached::class); EventFacade::assertNotDispatched(TenantPackageEventLimitReached::class); $tenantPackage->refresh(); $this->assertNotNull($tenantPackage->event_warning_sent_at); $this->assertSame(0.5, (float) $tenantPackage->event_warning_threshold); } public function test_record_event_usage_dispatches_limit_and_sets_timestamp(): void { EventFacade::fake([ TenantPackageEventThresholdReached::class, TenantPackageEventLimitReached::class, ]); Config::set('package-limits.event_thresholds', [0.5]); $tenant = Tenant::factory()->create(); $package = Package::factory()->reseller()->create([ 'max_events_per_year' => 3, ]); $tenantPackage = TenantPackage::factory() ->for($tenant) ->for($package) ->create([ 'used_events' => 3, ])->fresh(); /** @var TenantUsageTracker $tracker */ $tracker = app(TenantUsageTracker::class); $tracker->recordEventUsage($tenantPackage, 2, 1); EventFacade::assertDispatched(TenantPackageEventLimitReached::class); $tenantPackage->refresh(); $this->assertNotNull($tenantPackage->event_limit_notified_at); } public function test_record_credit_balance_dispatches_event_and_updates_tenant(): void { EventFacade::fake([TenantCreditsLow::class]); Config::set('package-limits.credit_thresholds', [5, 1]); $tenant = Tenant::factory()->create([ 'event_credits_balance' => 5, 'credit_warning_sent_at' => null, 'credit_warning_threshold' => null, ]); /** @var TenantUsageTracker $tracker */ $tracker = app(TenantUsageTracker::class); $tracker->recordCreditBalance($tenant, 6, 5); EventFacade::assertDispatched(TenantCreditsLow::class, function ($event) use ($tenant) { return $event->tenant->is($tenant) && $event->threshold === 5; }); $tenant->refresh(); $this->assertNotNull($tenant->credit_warning_sent_at); $this->assertSame(5, $tenant->credit_warning_threshold); } }