tenant; $eventType = EventType::factory()->create(); $package = Package::factory()->create(['type' => 'endcustomer', 'max_photos' => 100]); TenantPackage::factory()->create([ 'tenant_id' => $tenant->id, 'package_id' => $package->id, 'active' => true, ]); $purchase = PackagePurchase::factory()->create([ 'tenant_id' => $tenant->id, 'package_id' => $package->id, 'type' => 'endcustomer_event', 'metadata' => [], ]); $response = $this->authenticatedRequest('POST', '/api/v1/tenant/events', [ 'name' => 'Test Event', 'slug' => 'test-event', 'event_date' => Carbon::now()->addDays(10)->toDateString(), 'event_type_id' => $eventType->id, 'package_id' => $package->id, 'accepted_waiver' => true, ]); $response->assertStatus(201); $this->assertDatabaseHas('events', [ 'tenant_id' => $tenant->id, 'name' => json_encode('Test Event'), 'slug' => 'test-event', 'event_type_id' => $eventType->id, ]); $event = Event::latest()->first(); $this->assertDatabaseHas('event_packages', [ 'event_id' => $event->id, 'package_id' => $package->id, ]); $this->assertDatabaseHas('event_join_tokens', [ 'event_id' => $event->id, ]); $purchase->refresh(); $this->assertNotNull(data_get($purchase->metadata, 'consents.digital_content_waiver_at')); } public function test_create_event_without_package_fails(): void { $response = $this->authenticatedRequest('POST', '/api/v1/tenant/events', [ 'name' => 'Test Event', 'slug' => 'test-event', 'event_date' => Carbon::now()->addDays(10)->toDateString(), ]); $response->assertStatus(402) ->assertJsonPath('error.code', 'event_limit_missing'); } public function test_create_event_requires_waiver_for_endcustomer_package(): void { $tenant = $this->tenant; $eventType = EventType::factory()->create(); $package = Package::factory()->create(['type' => 'endcustomer', 'max_photos' => 100]); TenantPackage::factory()->create([ 'tenant_id' => $tenant->id, 'package_id' => $package->id, 'active' => true, ]); $response = $this->authenticatedRequest('POST', '/api/v1/tenant/events', [ 'name' => 'Test Event', 'slug' => 'test-event', 'event_date' => Carbon::now()->addDays(10)->toDateString(), 'event_type_id' => $eventType->id, 'package_id' => $package->id, 'accepted_waiver' => false, ]); $response->assertStatus(422) ->assertJsonValidationErrors(['accepted_waiver']); } public function test_create_event_with_reseller_package_limits_events(): void { $tenant = $this->tenant; $eventType = EventType::factory()->create(); $package = Package::factory()->create(['type' => 'reseller', 'max_events_per_year' => 1]); TenantPackage::factory()->create([ 'tenant_id' => $tenant->id, 'package_id' => $package->id, 'used_events' => 0, 'active' => true, 'expires_at' => now()->addYear(), ]); // First event succeeds $response1 = $this->authenticatedRequest('POST', '/api/v1/tenant/events', [ 'name' => 'First Event', 'slug' => 'first-event', 'event_date' => Carbon::now()->addDays(10)->toDateString(), 'event_type_id' => $eventType->id, 'package_id' => $package->id, // Use reseller package for event? Adjust if needed ]); $response1->assertStatus(201); // Second event fails due to limit $response2 = $this->authenticatedRequest('POST', '/api/v1/tenant/events', [ 'name' => 'Second Event', 'slug' => 'second-event', 'event_date' => Carbon::now()->addDays(11)->toDateString(), 'event_type_id' => $eventType->id, 'package_id' => $package->id, ]); $response2->assertStatus(402) ->assertJsonPath('error.code', 'event_limit_exceeded'); } public function test_upload_exceeds_package_limit_fails(): void { $tenant = $this->tenant; $event = Event::factory()->create(['tenant_id' => $tenant->id, 'status' => 'published']); $package = Package::factory()->create(['type' => 'endcustomer', 'max_photos' => 0]); // Limit 0 EventPackage::create([ 'event_id' => $event->id, 'package_id' => $package->id, 'purchased_price' => $package->price, 'used_photos' => 0, ]); Storage::fake('public'); $token = app(EventJoinTokenService::class)->createToken($event); $response = $this->withHeader('X-Device-Id', 'limit-test') ->post("/api/v1/events/{$token->token}/upload", [ 'photo' => UploadedFile::fake()->image('limit.jpg'), ]); $response->assertStatus(402) ->assertJsonPath('error.code', 'photo_limit_exceeded'); } }