Changeset View
Changeset View
Standalone View
Standalone View
src/tests/Feature/BillingTest.php
Show All 21 Lines | class BillingTest extends TestCase | ||||
public function setUp(): void | public function setUp(): void | ||||
{ | { | ||||
parent::setUp(); | parent::setUp(); | ||||
$this->deleteTestUser('jane@kolabnow.com'); | $this->deleteTestUser('jane@kolabnow.com'); | ||||
$this->deleteTestUser('jack@kolabnow.com'); | $this->deleteTestUser('jack@kolabnow.com'); | ||||
\App\Package::where('title', 'kolab-kube')->delete(); | \App\Package::withEnvTenantContext()->where('title', 'kolab-kube')->delete(); | ||||
$this->user = $this->getTestUser('jane@kolabnow.com'); | $this->user = $this->getTestUser('jane@kolabnow.com'); | ||||
$this->package = \App\Package::where('title', 'kolab')->first(); | $this->package = \App\Package::withEnvTenantContext()->where('title', 'kolab')->first(); | ||||
$this->user->assignPackage($this->package); | $this->user->assignPackage($this->package); | ||||
$this->wallet = $this->user->wallets->first(); | $this->wallet = $this->user->wallets->first(); | ||||
$this->wallet_id = $this->wallet->id; | $this->wallet_id = $this->wallet->id; | ||||
} | } | ||||
public function tearDown(): void | public function tearDown(): void | ||||
{ | { | ||||
$this->deleteTestUser('jane@kolabnow.com'); | $this->deleteTestUser('jane@kolabnow.com'); | ||||
$this->deleteTestUser('jack@kolabnow.com'); | $this->deleteTestUser('jack@kolabnow.com'); | ||||
\App\Package::where('title', 'kolab-kube')->delete(); | \App\Package::withEnvTenantContext()->where('title', 'kolab-kube')->delete(); | ||||
parent::tearDown(); | parent::tearDown(); | ||||
} | } | ||||
/** | /** | ||||
* Test the expected results for a user that registers and is almost immediately gone. | * Test the expected results for a user that registers and is almost immediately gone. | ||||
*/ | */ | ||||
public function testTouchAndGo(): void | public function testTouchAndGo(): void | ||||
{ | { | ||||
$this->assertCount(4, $this->wallet->entitlements); | $this->assertCount(7, $this->wallet->entitlements); | ||||
$this->assertEquals(0, $this->wallet->expectedCharges()); | $this->assertEquals(0, $this->wallet->expectedCharges()); | ||||
$this->user->delete(); | $this->user->delete(); | ||||
$this->assertCount(0, $this->wallet->fresh()->entitlements->where('deleted_at', null)); | $this->assertCount(0, $this->wallet->fresh()->entitlements->where('deleted_at', null)); | ||||
$this->assertCount(4, $this->wallet->entitlements); | $this->assertCount(7, $this->wallet->entitlements); | ||||
} | } | ||||
/** | /** | ||||
* Verify the last day before the end of a full month's trial. | * Verify the last day before the end of a full month's trial. | ||||
*/ | */ | ||||
public function testNearFullTrial(): void | public function testNearFullTrial(): void | ||||
{ | { | ||||
$this->backdateEntitlements( | $this->backdateEntitlements( | ||||
Show All 9 Lines | class BillingTest extends TestCase | ||||
*/ | */ | ||||
public function testFullTrial(): void | public function testFullTrial(): void | ||||
{ | { | ||||
$this->backdateEntitlements( | $this->backdateEntitlements( | ||||
$this->wallet->entitlements, | $this->wallet->entitlements, | ||||
Carbon::now()->subMonthsWithoutOverflow(1) | Carbon::now()->subMonthsWithoutOverflow(1) | ||||
); | ); | ||||
$this->assertEquals(999, $this->wallet->expectedCharges()); | $this->assertEquals(990, $this->wallet->expectedCharges()); | ||||
} | } | ||||
/** | /** | ||||
* Verify that over-running the trial by a single day causes charges to be incurred. | * Verify that over-running the trial by a single day causes charges to be incurred. | ||||
*/ | */ | ||||
public function testOutRunTrial(): void | public function testOutRunTrial(): void | ||||
{ | { | ||||
$this->backdateEntitlements( | $this->backdateEntitlements( | ||||
$this->wallet->entitlements, | $this->wallet->entitlements, | ||||
Carbon::now()->subMonthsWithoutOverflow(1)->subDays(1) | Carbon::now()->subMonthsWithoutOverflow(1)->subDays(1) | ||||
); | ); | ||||
$this->assertEquals(999, $this->wallet->expectedCharges()); | $this->assertEquals(990, $this->wallet->expectedCharges()); | ||||
} | } | ||||
/** | /** | ||||
* Verify additional storage configuration entitlement created 'early' does incur additional | * Verify additional storage configuration entitlement created 'early' does incur additional | ||||
* charges to the wallet. | * charges to the wallet. | ||||
*/ | */ | ||||
public function testAddtStorageEarly(): void | public function testAddtStorageEarly(): void | ||||
{ | { | ||||
$this->backdateEntitlements( | $this->backdateEntitlements( | ||||
$this->wallet->entitlements, | $this->wallet->entitlements, | ||||
Carbon::now()->subMonthsWithoutOverflow(1)->subDays(1) | Carbon::now()->subMonthsWithoutOverflow(1)->subDays(1) | ||||
); | ); | ||||
$this->assertEquals(999, $this->wallet->expectedCharges()); | $this->assertEquals(990, $this->wallet->expectedCharges()); | ||||
$sku = \App\Sku::where(['title' => 'storage'])->first(); | $sku = \App\Sku::withEnvTenantContext()->where('title', 'storage')->first(); | ||||
$entitlement = \App\Entitlement::create( | $entitlement = \App\Entitlement::create( | ||||
[ | [ | ||||
'wallet_id' => $this->wallet_id, | 'wallet_id' => $this->wallet_id, | ||||
'sku_id' => $sku->id, | 'sku_id' => $sku->id, | ||||
'cost' => $sku->cost, | 'cost' => $sku->cost, | ||||
'entitleable_id' => $this->user->id, | 'entitleable_id' => $this->user->id, | ||||
'entitleable_type' => \App\User::class | 'entitleable_type' => \App\User::class | ||||
] | ] | ||||
); | ); | ||||
$this->backdateEntitlements( | $this->backdateEntitlements( | ||||
[$entitlement], | [$entitlement], | ||||
Carbon::now()->subMonthsWithoutOverflow(1)->subDays(1) | Carbon::now()->subMonthsWithoutOverflow(1)->subDays(1) | ||||
); | ); | ||||
$this->assertEquals(1024, $this->wallet->expectedCharges()); | $this->assertEquals(1015, $this->wallet->expectedCharges()); | ||||
} | } | ||||
/** | /** | ||||
* Verify additional storage configuration entitlement created 'late' does not incur additional | * Verify additional storage configuration entitlement created 'late' does not incur additional | ||||
* charges to the wallet. | * charges to the wallet. | ||||
*/ | */ | ||||
public function testAddtStorageLate(): void | public function testAddtStorageLate(): void | ||||
{ | { | ||||
$this->backdateEntitlements($this->wallet->entitlements, Carbon::now()->subMonthsWithoutOverflow(1)); | $this->backdateEntitlements($this->wallet->entitlements, Carbon::now()->subMonthsWithoutOverflow(1)); | ||||
$this->assertEquals(999, $this->wallet->expectedCharges()); | $this->assertEquals(990, $this->wallet->expectedCharges()); | ||||
$sku = \App\Sku::where(['title' => 'storage'])->first(); | $sku = \App\Sku::withEnvTenantContext()->where(['title' => 'storage'])->first(); | ||||
$entitlement = \App\Entitlement::create( | $entitlement = \App\Entitlement::create( | ||||
[ | [ | ||||
'wallet_id' => $this->wallet_id, | 'wallet_id' => $this->wallet_id, | ||||
'sku_id' => $sku->id, | 'sku_id' => $sku->id, | ||||
'cost' => $sku->cost, | 'cost' => $sku->cost, | ||||
'entitleable_id' => $this->user->id, | 'entitleable_id' => $this->user->id, | ||||
'entitleable_type' => \App\User::class | 'entitleable_type' => \App\User::class | ||||
] | ] | ||||
); | ); | ||||
$this->backdateEntitlements([$entitlement], Carbon::now()->subDays(14)); | $this->backdateEntitlements([$entitlement], Carbon::now()->subDays(14)); | ||||
$this->assertEquals(999, $this->wallet->expectedCharges()); | $this->assertEquals(990, $this->wallet->expectedCharges()); | ||||
} | } | ||||
public function testFifthWeek(): void | public function testFifthWeek(): void | ||||
{ | { | ||||
$targetDateA = Carbon::now()->subWeeks(5); | $targetDateA = Carbon::now()->subWeeks(5); | ||||
$targetDateB = $targetDateA->copy()->addMonthsWithoutOverflow(1); | $targetDateB = $targetDateA->copy()->addMonthsWithoutOverflow(1); | ||||
$this->backdateEntitlements($this->wallet->entitlements, $targetDateA); | $this->backdateEntitlements($this->wallet->entitlements, $targetDateA); | ||||
$this->assertEquals(999, $this->wallet->expectedCharges()); | $this->assertEquals(990, $this->wallet->expectedCharges()); | ||||
$this->wallet->chargeEntitlements(); | $this->wallet->chargeEntitlements(); | ||||
$this->assertEquals(-999, $this->wallet->balance); | $this->assertEquals(-990, $this->wallet->balance); | ||||
foreach ($this->wallet->entitlements()->get() as $entitlement) { | foreach ($this->wallet->entitlements()->get() as $entitlement) { | ||||
$this->assertTrue($entitlement->created_at->isSameSecond($targetDateA)); | $this->assertTrue($entitlement->created_at->isSameSecond($targetDateA)); | ||||
$this->assertTrue($entitlement->updated_at->isSameSecond($targetDateB)); | $this->assertTrue($entitlement->updated_at->isSameSecond($targetDateB)); | ||||
} | } | ||||
} | } | ||||
public function testSecondMonth(): void | public function testSecondMonth(): void | ||||
{ | { | ||||
$this->backdateEntitlements($this->wallet->entitlements, Carbon::now()->subMonthsWithoutOverflow(2)); | $this->backdateEntitlements($this->wallet->entitlements, Carbon::now()->subMonthsWithoutOverflow(2)); | ||||
$this->assertCount(4, $this->wallet->entitlements); | $this->assertCount(7, $this->wallet->entitlements); | ||||
$this->assertEquals(1998, $this->wallet->expectedCharges()); | $this->assertEquals(1980, $this->wallet->expectedCharges()); | ||||
$sku = \App\Sku::where(['title' => 'storage'])->first(); | $sku = \App\Sku::withEnvTenantContext()->where('title', 'storage')->first(); | ||||
$entitlement = \App\Entitlement::create( | $entitlement = \App\Entitlement::create( | ||||
[ | [ | ||||
'entitleable_id' => $this->user->id, | 'entitleable_id' => $this->user->id, | ||||
'entitleable_type' => \App\User::class, | 'entitleable_type' => \App\User::class, | ||||
'cost' => $sku->cost, | 'cost' => $sku->cost, | ||||
'sku_id' => $sku->id, | 'sku_id' => $sku->id, | ||||
'wallet_id' => $this->wallet_id | 'wallet_id' => $this->wallet_id | ||||
] | ] | ||||
); | ); | ||||
$this->backdateEntitlements([$entitlement], Carbon::now()->subMonthsWithoutOverflow(1)); | $this->backdateEntitlements([$entitlement], Carbon::now()->subMonthsWithoutOverflow(1)); | ||||
$this->assertEquals(2023, $this->wallet->expectedCharges()); | $this->assertEquals(2005, $this->wallet->expectedCharges()); | ||||
} | } | ||||
public function testWithDiscountRate(): void | public function testWithDiscountRate(): void | ||||
{ | { | ||||
$package = \App\Package::create( | $package = \App\Package::create( | ||||
[ | [ | ||||
'title' => 'kolab-kube', | 'title' => 'kolab-kube', | ||||
'name' => 'Kolab for Kuba Fans', | 'name' => 'Kolab for Kuba Fans', | ||||
'description' => 'Kolab for Kube fans', | 'description' => 'Kolab for Kube fans', | ||||
'discount_rate' => 50 | 'discount_rate' => 50 | ||||
] | ] | ||||
); | ); | ||||
$skus = [ | $skus = [ | ||||
\App\Sku::firstOrCreate(['title' => 'mailbox']), | \App\Sku::withEnvTenantContext()->where('title', 'mailbox')->first(), | ||||
\App\Sku::firstOrCreate(['title' => 'storage']), | \App\Sku::withEnvTenantContext()->where('title', 'storage')->first(), | ||||
\App\Sku::firstOrCreate(['title' => 'groupware']) | \App\Sku::withEnvTenantContext()->where('title', 'groupware')->first() | ||||
]; | ]; | ||||
$package->skus()->saveMany($skus); | $package->skus()->saveMany($skus); | ||||
$package->skus()->updateExistingPivot( | $package->skus()->updateExistingPivot( | ||||
\App\Sku::firstOrCreate(['title' => 'storage']), | \App\Sku::withEnvTenantContext()->where('title', 'storage')->first(), | ||||
['qty' => 2], | ['qty' => 5], | ||||
false | false | ||||
); | ); | ||||
$user = $this->getTestUser('jack@kolabnow.com'); | $user = $this->getTestUser('jack@kolabnow.com'); | ||||
$user->assignPackage($package); | $user->assignPackage($package); | ||||
$wallet = $user->wallets->first(); | $wallet = $user->wallets->first(); | ||||
$wallet_id = $wallet->id; | $wallet_id = $wallet->id; | ||||
$this->backdateEntitlements($wallet->entitlements, Carbon::now()->subMonthsWithoutOverflow(1)); | $this->backdateEntitlements($wallet->entitlements, Carbon::now()->subMonthsWithoutOverflow(1)); | ||||
$this->assertEquals(500, $wallet->expectedCharges()); | $this->assertEquals(495, $wallet->expectedCharges()); | ||||
} | } | ||||
/** | /** | ||||
* Test cost calculation with a wallet discount | * Test cost calculation with a wallet discount | ||||
*/ | */ | ||||
public function testWithWalletDiscount(): void | public function testWithWalletDiscount(): void | ||||
{ | { | ||||
$discount = \App\Discount::where('code', 'TEST')->first(); | $discount = \App\Discount::withEnvTenantContext()->where('code', 'TEST')->first(); | ||||
$wallet = $this->user->wallets()->first(); | $wallet = $this->user->wallets()->first(); | ||||
$wallet->discount()->associate($discount); | $wallet->discount()->associate($discount); | ||||
$this->backdateEntitlements($wallet->entitlements, Carbon::now()->subMonthsWithoutOverflow(1)); | $this->backdateEntitlements($wallet->entitlements, Carbon::now()->subMonthsWithoutOverflow(1)); | ||||
$this->assertEquals(898, $wallet->expectedCharges()); | $this->assertEquals(891, $wallet->expectedCharges()); | ||||
} | } | ||||
} | } |