removed all references to credits. now credits are completely replaced by addons.
This commit is contained in:
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use App\Filament\Widgets\CreditAlertsWidget;
|
||||
use App\Filament\Widgets\RevenueTrendWidget;
|
||||
use App\Models\PurchaseHistory;
|
||||
use App\Models\Tenant;
|
||||
@@ -21,67 +20,17 @@ class AdminDashboardWidgetsTest extends TestCase
|
||||
Carbon::setTestNow();
|
||||
}
|
||||
|
||||
public function test_credit_alerts_widget_cards_reflect_metrics(): void
|
||||
{
|
||||
$lowBalanceTenant = Tenant::factory()->create([
|
||||
'event_credits_balance' => 2,
|
||||
'is_active' => true,
|
||||
'subscription_expires_at' => now()->addMonths(2),
|
||||
]);
|
||||
|
||||
Tenant::factory()->create([
|
||||
'event_credits_balance' => 20,
|
||||
'is_active' => true,
|
||||
'subscription_expires_at' => now()->addMonths(1),
|
||||
]);
|
||||
|
||||
Tenant::factory()->create([
|
||||
'event_credits_balance' => 1,
|
||||
'is_active' => false,
|
||||
'subscription_expires_at' => now()->subDay(),
|
||||
]);
|
||||
|
||||
PurchaseHistory::create([
|
||||
'id' => 'ph-1',
|
||||
'tenant_id' => $lowBalanceTenant->id,
|
||||
'package_id' => 'starter_pack',
|
||||
'credits_added' => 5,
|
||||
'price' => 149.90,
|
||||
'currency' => 'EUR',
|
||||
'platform' => 'web',
|
||||
'transaction_id' => 'txn-1',
|
||||
'purchased_at' => now()->startOfMonth()->addDay(),
|
||||
'created_at' => now(),
|
||||
]);
|
||||
|
||||
$widget = new CreditAlertsWidget();
|
||||
|
||||
$cards = $this->invokeProtectedMethod($widget, 'getCards');
|
||||
|
||||
$this->assertCount(3, $cards);
|
||||
$this->assertSame(
|
||||
__('admin.widgets.credit_alerts.low_balance_label'),
|
||||
$cards[0]->getLabel()
|
||||
);
|
||||
$this->assertSame(1, $cards[0]->getValue());
|
||||
$this->assertSame(
|
||||
2,
|
||||
$cards[2]->getValue()
|
||||
);
|
||||
$this->assertStringContainsString('149.9', (string) $cards[1]->getValue());
|
||||
}
|
||||
|
||||
public function test_revenue_trend_widget_compiles_monthly_totals(): void
|
||||
{
|
||||
Carbon::setTestNow(Carbon::create(2025, 10, 20, 12));
|
||||
|
||||
$tenant = Tenant::factory()->create();
|
||||
$packagePro = \App\Models\Package::factory()->create(['name' => 'Pro Pack']);
|
||||
$packageStarter = \App\Models\Package::factory()->create(['name' => 'Starter Pack']);
|
||||
|
||||
PurchaseHistory::create([
|
||||
'id' => 'cur-1',
|
||||
'tenant_id' => $tenant->id,
|
||||
'package_id' => 'pro_pack',
|
||||
'credits_added' => 10,
|
||||
'package_id' => $packagePro->id,
|
||||
'price' => 299.99,
|
||||
'currency' => 'EUR',
|
||||
'platform' => 'web',
|
||||
@@ -91,10 +40,8 @@ class AdminDashboardWidgetsTest extends TestCase
|
||||
]);
|
||||
|
||||
PurchaseHistory::create([
|
||||
'id' => 'prev-1',
|
||||
'tenant_id' => $tenant->id,
|
||||
'package_id' => 'starter_pack',
|
||||
'credits_added' => 5,
|
||||
'package_id' => $packageStarter->id,
|
||||
'price' => 149.90,
|
||||
'currency' => 'EUR',
|
||||
'platform' => 'web',
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use App\Jobs\ProcessRevenueCatWebhook;
|
||||
use App\Models\Tenant;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ProcessRevenueCatWebhookTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_job_creates_purchase_and_updates_balance(): void
|
||||
{
|
||||
config()->set('services.revenuecat.product_mappings', 'pro_month:5');
|
||||
$tenant = Tenant::factory()->create([
|
||||
'event_credits_balance' => 1,
|
||||
'subscription_tier' => 'free',
|
||||
]);
|
||||
|
||||
$expiresAt = Carbon::now()->addDays(30)->setTimezone('UTC')->floorSecond();
|
||||
$payload = [
|
||||
'event' => [
|
||||
'app_user_id' => 'tenant:' . $tenant->id,
|
||||
'product_id' => 'pro_month',
|
||||
'transaction_id' => 'txn-test-1',
|
||||
'price' => 19.99,
|
||||
'currency' => 'eur',
|
||||
'expiration_at_ms' => (int) ($expiresAt->valueOf()),
|
||||
],
|
||||
];
|
||||
|
||||
$job = new ProcessRevenueCatWebhook($payload, 'evt-test-1');
|
||||
$job->handle();
|
||||
|
||||
$tenant->refresh();
|
||||
$this->assertSame(6, $tenant->event_credits_balance);
|
||||
$this->assertSame('pro', $tenant->subscription_tier);
|
||||
$this->assertNotNull($tenant->subscription_expires_at);
|
||||
$expected = $expiresAt->clone()->setTimezone(config('app.timezone'));
|
||||
$this->assertLessThanOrEqual(3600, abs($tenant->subscription_expires_at->timestamp - $expected->timestamp));
|
||||
|
||||
$this->assertDatabaseHas('event_purchases', [
|
||||
'tenant_id' => $tenant->id,
|
||||
'provider' => 'revenuecat',
|
||||
'external_receipt_id' => 'txn-test-1',
|
||||
'events_purchased' => 5,
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('event_credits_ledger', [
|
||||
'tenant_id' => $tenant->id,
|
||||
'delta' => 5,
|
||||
'reason' => 'purchase',
|
||||
]);
|
||||
|
||||
$duplicateJob = new ProcessRevenueCatWebhook($payload, 'evt-test-1');
|
||||
$duplicateJob->handle();
|
||||
|
||||
$this->assertSame(6, $tenant->fresh()->event_credits_balance);
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,13 @@ class PackageLimitEvaluatorTest extends TestCase
|
||||
|
||||
public function test_assess_event_creation_returns_null_when_allowance_available(): void
|
||||
{
|
||||
$tenant = Tenant::factory()->create(['event_credits_balance' => 2]);
|
||||
$tenant = Tenant::factory()->create();
|
||||
$package = Package::factory()->reseller()->create(['max_events_per_year' => 5]);
|
||||
TenantPackage::factory()->for($tenant)->for($package)->create([
|
||||
'used_events' => 1,
|
||||
'expires_at' => now()->addMonth(),
|
||||
'active' => true,
|
||||
]);
|
||||
|
||||
$violation = $this->evaluator->assessEventCreation($tenant);
|
||||
|
||||
@@ -39,7 +45,7 @@ class PackageLimitEvaluatorTest extends TestCase
|
||||
'max_events_per_year' => 1,
|
||||
]);
|
||||
|
||||
$tenant = Tenant::factory()->create(['event_credits_balance' => 0]);
|
||||
$tenant = Tenant::factory()->create();
|
||||
|
||||
TenantPackage::factory()->create([
|
||||
'tenant_id' => $tenant->id,
|
||||
@@ -59,17 +65,6 @@ class PackageLimitEvaluatorTest extends TestCase
|
||||
$this->assertSame(0, $violation['meta']['remaining']);
|
||||
}
|
||||
|
||||
public function test_assess_event_creation_returns_credit_violation_when_no_credits(): void
|
||||
{
|
||||
$tenant = Tenant::factory()->create(['event_credits_balance' => 0]);
|
||||
|
||||
$violation = $this->evaluator->assessEventCreation($tenant);
|
||||
|
||||
$this->assertNotNull($violation);
|
||||
$this->assertSame('event_credits_exhausted', $violation['code']);
|
||||
$this->assertSame('credits', $violation['meta']['scope']);
|
||||
}
|
||||
|
||||
public function test_assess_photo_upload_returns_violation_when_photo_limit_reached(): void
|
||||
{
|
||||
$package = Package::factory()->endcustomer()->create([
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Tests\Unit\Services;
|
||||
|
||||
use App\Events\Packages\TenantCreditsLow;
|
||||
use App\Events\Packages\TenantPackageEventLimitReached;
|
||||
use App\Events\Packages\TenantPackageEventThresholdReached;
|
||||
use App\Models\Package;
|
||||
@@ -85,31 +84,4 @@ class TenantUsageTrackerTest extends TestCase
|
||||
|
||||
$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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use App\Models\Package;
|
||||
use App\Models\Tenant;
|
||||
use App\Models\TenantPackage;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class TenantCreditTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_consume_event_allowance_uses_reseller_package(): void
|
||||
{
|
||||
$package = Package::factory()
|
||||
->reseller()
|
||||
->create([
|
||||
'max_events_per_year' => 5,
|
||||
]);
|
||||
|
||||
$tenant = Tenant::factory()->create([
|
||||
'event_credits_balance' => 0,
|
||||
]);
|
||||
|
||||
TenantPackage::factory()->for($tenant)->for($package)->create([
|
||||
'used_events' => 1,
|
||||
'active' => true,
|
||||
]);
|
||||
|
||||
$this->assertTrue($tenant->consumeEventAllowance());
|
||||
|
||||
$updatedPackage = $tenant->getActiveResellerPackage();
|
||||
$this->assertNotNull($updatedPackage);
|
||||
$this->assertSame(2, $updatedPackage->used_events);
|
||||
}
|
||||
|
||||
public function test_consume_event_allowance_decrements_credits_when_no_package(): void
|
||||
{
|
||||
$tenant = Tenant::factory()->create([
|
||||
'event_credits_balance' => 2,
|
||||
]);
|
||||
|
||||
$this->assertTrue($tenant->consumeEventAllowance(1, 'event.create', 'Event #1 created'));
|
||||
|
||||
$tenant->refresh();
|
||||
$this->assertSame(1, $tenant->event_credits_balance);
|
||||
|
||||
$this->assertDatabaseHas('event_credits_ledger', [
|
||||
'tenant_id' => $tenant->id,
|
||||
'delta' => -1,
|
||||
'reason' => 'event.create',
|
||||
'note' => 'Event #1 created',
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_consume_event_allowance_returns_false_without_package_or_credits(): void
|
||||
{
|
||||
$tenant = Tenant::factory()->create([
|
||||
'event_credits_balance' => 0,
|
||||
]);
|
||||
|
||||
$this->assertFalse($tenant->consumeEventAllowance());
|
||||
|
||||
$this->assertDatabaseCount('event_credits_ledger', 0);
|
||||
}
|
||||
}
|
||||
@@ -146,22 +146,4 @@ class TenantModelTest extends TestCase
|
||||
$this->assertFalse($tenant->features['analytics']);
|
||||
}
|
||||
|
||||
public function test_increment_credits_clears_warning_when_balance_above_threshold(): void
|
||||
{
|
||||
Config::set('package-limits.credit_thresholds', [5, 1]);
|
||||
|
||||
$tenant = Tenant::factory()->create([
|
||||
'event_credits_balance' => 1,
|
||||
'credit_warning_sent_at' => now()->subDay(),
|
||||
'credit_warning_threshold' => 1,
|
||||
]);
|
||||
|
||||
$tenant->incrementCredits(10);
|
||||
|
||||
$tenant->refresh();
|
||||
|
||||
$this->assertNull($tenant->credit_warning_sent_at);
|
||||
$this->assertNull($tenant->credit_warning_threshold);
|
||||
$this->assertSame(11, (int) $tenant->event_credits_balance);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use App\Models\Tenant;
|
||||
use App\Models\User;
|
||||
use App\Policies\TenantPolicy;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class TenantPolicyTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
protected TenantPolicy $policy;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->policy = new TenantPolicy();
|
||||
}
|
||||
|
||||
public function test_super_admin_can_adjust_credits(): void
|
||||
{
|
||||
$tenant = Tenant::factory()->create();
|
||||
$user = User::factory()->create([
|
||||
'role' => 'super_admin',
|
||||
]);
|
||||
|
||||
$this->assertTrue($this->policy->adjustCredits($user, $tenant));
|
||||
}
|
||||
|
||||
public function test_tenant_admin_cannot_adjust_credits(): void
|
||||
{
|
||||
$tenant = Tenant::factory()->create();
|
||||
$user = User::factory()->create([
|
||||
'role' => 'tenant_admin',
|
||||
]);
|
||||
|
||||
$user->forceFill(['tenant_id' => $tenant->id])->save();
|
||||
|
||||
$this->assertFalse($this->policy->adjustCredits($user, $tenant));
|
||||
}
|
||||
|
||||
public function test_tenant_admin_can_view_own_tenant(): void
|
||||
{
|
||||
$tenant = Tenant::factory()->create();
|
||||
$user = User::factory()->create([
|
||||
'role' => 'tenant_admin',
|
||||
]);
|
||||
|
||||
$user->forceFill(['tenant_id' => $tenant->id])->save();
|
||||
|
||||
$this->assertTrue($this->policy->view($user, $tenant));
|
||||
}
|
||||
|
||||
public function test_tenant_admin_cannot_view_other_tenant(): void
|
||||
{
|
||||
$tenant = Tenant::factory()->create();
|
||||
$otherTenant = Tenant::factory()->create();
|
||||
|
||||
$user = User::factory()->create([
|
||||
'role' => 'tenant_admin',
|
||||
]);
|
||||
|
||||
$user->forceFill(['tenant_id' => $tenant->id])->save();
|
||||
|
||||
$this->assertFalse($this->policy->view($user, $otherTenant));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user