create([ 'lemonsqueezy_variant_id' => 'pri_test', 'price' => 100, ]); $coupon = Coupon::factory()->create([ 'code' => 'SAVE20', 'type' => CouponType::PERCENTAGE, 'amount' => 20, 'lemonsqueezy_discount_id' => 'dsc_123', 'per_customer_limit' => null, ]); $coupon->packages()->attach($package); $response = $this->postJson(route('api.v1.marketing.coupons.preview'), [ 'package_id' => $package->id, 'code' => 'save20', ]); $response->assertOk() ->assertJsonPath('coupon.code', 'SAVE20'); $this->assertEquals(80.0, (float) $response->json('pricing.total')); } public function test_invalid_coupon_returns_validation_error(): void { $package = Package::factory()->create([ 'lemonsqueezy_variant_id' => 'pri_test_invalid', ]); $this->postJson(route('api.v1.marketing.coupons.preview'), [ 'package_id' => $package->id, 'code' => 'UNKNOWN', ])->assertUnprocessable() ->assertJsonValidationErrors('code'); } public function test_coupon_with_per_customer_limit_requires_login(): void { $package = Package::factory()->create([ 'lemonsqueezy_variant_id' => 'pri_test_login', ]); $coupon = Coupon::factory()->create([ 'code' => 'LIMITED', 'lemonsqueezy_discount_id' => 'dsc_login', 'per_customer_limit' => 1, ]); $coupon->packages()->attach($package); $response = $this->postJson(route('api.v1.marketing.coupons.preview'), [ 'package_id' => $package->id, 'code' => 'LIMITED', ]); $response->assertUnprocessable() ->assertJsonValidationErrors('code'); $this->assertSame( __('marketing.coupon.errors.login_required'), $response->json('errors.code.0') ); } public function test_coupon_with_per_customer_limit_allows_logged_in_tenant(): void { $tenant = Tenant::factory()->create(); $user = User::factory()->create([ 'tenant_id' => $tenant->id, ]); $package = Package::factory()->create([ 'lemonsqueezy_variant_id' => 'pri_test_logged_in', 'price' => 120, ]); $coupon = Coupon::factory()->create([ 'code' => 'LIMITEDTENANT', 'type' => CouponType::FLAT, 'amount' => 20, 'currency' => 'EUR', 'lemonsqueezy_discount_id' => 'dsc_logged_in', 'per_customer_limit' => 1, ]); $coupon->packages()->attach($package); $response = $this->actingAs($user)->postJson(route('api.v1.marketing.coupons.preview'), [ 'package_id' => $package->id, 'code' => 'limitedtenant', ]); $response->assertOk() ->assertJsonPath('coupon.code', 'LIMITEDTENANT'); $this->assertEquals(100.0, (float) $response->json('pricing.total')); } }