110 lines
4.0 KiB
PHP
110 lines
4.0 KiB
PHP
<?php
|
|
|
|
use App\Livewire\Admin\Customers;
|
|
use App\Livewire\Admin\GrantPlan;
|
|
use App\Models\Customer;
|
|
use App\Models\Subscription;
|
|
use App\Models\SubscriptionAddon;
|
|
use App\Provisioning\Jobs\AdvanceRunJob;
|
|
use Illuminate\Support\Facades\Queue;
|
|
use Livewire\Livewire;
|
|
|
|
/**
|
|
* The console's side of granting: a modal (R20) on the customer's own row,
|
|
* gated by its own capability rather than merely hidden (mutation target #3).
|
|
*
|
|
* 'fsn' is seeded by the datacenters migration itself (baseline data, like
|
|
* the mailbox seeding) — no factory needed for it here.
|
|
*/
|
|
it('refuses to open for an operator without the capability, not merely hides the button', function () {
|
|
$customer = Customer::factory()->create();
|
|
|
|
// Support has customers.manage (can suspend, impersonate) but never had
|
|
// customers.grant_plan — giving away service is a bigger deal than a
|
|
// reversible suspend, and the seed migration deliberately keeps this one
|
|
// to Owner. A capability check that only hid the button would still let
|
|
// this request through.
|
|
Livewire::actingAs(operator('Support'), 'operator')
|
|
->test(GrantPlan::class, ['uuid' => $customer->uuid])
|
|
->assertForbidden();
|
|
});
|
|
|
|
it('hides the grant button from an operator without the capability', function () {
|
|
Customer::factory()->create();
|
|
|
|
Livewire::actingAs(operator('Support'), 'operator')
|
|
->test(Customers::class)
|
|
->assertDontSee(__('admin.grant_action'));
|
|
});
|
|
|
|
it('shows the grant button to the Owner', function () {
|
|
Customer::factory()->create();
|
|
|
|
Livewire::actingAs(operator('Owner'), 'operator')
|
|
->test(Customers::class)
|
|
->assertSee(__('admin.grant_action'));
|
|
});
|
|
|
|
it('grants a free package to a customer with no contract yet', function () {
|
|
Queue::fake();
|
|
$customer = Customer::factory()->create();
|
|
$owner = operator('Owner');
|
|
|
|
Livewire::actingAs($owner, 'operator')
|
|
->test(GrantPlan::class, ['uuid' => $customer->uuid])
|
|
->set('plan', 'team')
|
|
->set('term', 'monthly')
|
|
->set('datacenter', 'fsn')
|
|
->set('priceEuros', '0')
|
|
->set('note', 'Testkunde')
|
|
->call('grant')
|
|
->assertHasNoErrors();
|
|
|
|
$subscription = Subscription::query()->where('customer_id', $customer->id)->sole();
|
|
|
|
expect($subscription->price_cents)->toBe(0)
|
|
->and($subscription->isGranted())->toBeTrue()
|
|
->and($subscription->granted_by)->toBe($owner->id);
|
|
|
|
Queue::assertPushed(AdvanceRunJob::class);
|
|
});
|
|
|
|
it('grants a discounted module onto an existing contract', function () {
|
|
$customer = Customer::factory()->create();
|
|
Subscription::factory()->create(['customer_id' => $customer->id, 'status' => 'active']);
|
|
$owner = operator('Owner');
|
|
|
|
Livewire::actingAs($owner, 'operator')
|
|
->test(GrantPlan::class, ['uuid' => $customer->uuid])
|
|
->assertSet('kind', 'addon') // a contract already exists — default to the module form
|
|
->set('addonKey', 'priority_support')
|
|
->set('quantity', 1)
|
|
->set('priceEuros', '5,00')
|
|
->call('grant')
|
|
->assertHasNoErrors();
|
|
|
|
$addon = SubscriptionAddon::query()->where('addon_key', 'priority_support')->sole();
|
|
|
|
expect($addon->price_cents)->toBe(500)
|
|
->and($addon->isGranted())->toBeTrue()
|
|
->and($addon->granted_by)->toBe($owner->id);
|
|
});
|
|
|
|
it('shows who granted what, when, and until when', function () {
|
|
$customer = Customer::factory()->create();
|
|
$owner = operator('Owner');
|
|
$until = now()->addMonths(3);
|
|
|
|
Subscription::factory()->create([
|
|
'customer_id' => $customer->id, 'status' => 'active',
|
|
'price_cents' => 0, 'granted_by' => $owner->id, 'granted_at' => now(),
|
|
'grant_note' => 'Sponsoring', 'granted_until' => $until, 'catalogue_price_cents' => 17900,
|
|
]);
|
|
|
|
Livewire::actingAs($owner, 'operator')
|
|
->test(GrantPlan::class, ['uuid' => $customer->uuid])
|
|
->assertSee($owner->name)
|
|
->assertSee('Sponsoring')
|
|
->assertSee($until->local()->isoFormat('D. MMM YYYY'));
|
|
});
|