78 lines
2.4 KiB
PHP
78 lines
2.4 KiB
PHP
|
|
<?php
|
|||
|
|
|
|||
|
|
declare(strict_types=1);
|
|||
|
|
|
|||
|
|
use App\Models\BalanceTransaction;
|
|||
|
|
use App\Models\PricingTier;
|
|||
|
|
use App\Models\Tenant;
|
|||
|
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
|||
|
|
|
|||
|
|
uses(DatabaseTransactions::class);
|
|||
|
|
|
|||
|
|
beforeEach(function () {
|
|||
|
|
// Custom tier 1 with effective_from in the past — overrides PricingTierSeeder's '1970-01-01' default.
|
|||
|
|
PricingTier::query()->delete();
|
|||
|
|
PricingTier::create([
|
|||
|
|
'tier_no' => 1,
|
|||
|
|
'leads_in_tier' => 50,
|
|||
|
|
'price_per_lead_kopecks' => 12000,
|
|||
|
|
'is_active' => true,
|
|||
|
|
'effective_from' => now()->subDay()->toDateString(),
|
|||
|
|
]);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('migrates balance_leads to balance_rub at tier 1 price', function () {
|
|||
|
|
$tenant = Tenant::factory()->create([
|
|||
|
|
'balance_leads' => 5,
|
|||
|
|
'balance_rub' => '100.00',
|
|||
|
|
]);
|
|||
|
|
|
|||
|
|
$this->artisan('billing:migrate-leads-to-rub')->assertOk();
|
|||
|
|
|
|||
|
|
$tenant->refresh();
|
|||
|
|
expect($tenant->balance_leads)->toBe(0);
|
|||
|
|
expect((string) $tenant->balance_rub)->toBe('700.00'); // 100 + 5×120 = 700
|
|||
|
|
|
|||
|
|
$tx = BalanceTransaction::where('tenant_id', $tenant->id)
|
|||
|
|
->where('type', BalanceTransaction::TYPE_MIGRATION)
|
|||
|
|
->first();
|
|||
|
|
|
|||
|
|
expect($tx)->not->toBeNull();
|
|||
|
|
expect((int) $tx->amount_leads)->toBe(-5);
|
|||
|
|
expect((string) $tx->amount_rub)->toBe('600.00');
|
|||
|
|
expect((string) $tx->balance_rub_after)->toBe('700.00');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('is idempotent — second run is no-op', function () {
|
|||
|
|
$tenant = Tenant::factory()->create([
|
|||
|
|
'balance_leads' => 5,
|
|||
|
|
'balance_rub' => '100.00',
|
|||
|
|
]);
|
|||
|
|
|
|||
|
|
$this->artisan('billing:migrate-leads-to-rub')->assertOk();
|
|||
|
|
$balanceAfterFirst = $tenant->fresh()->balance_rub;
|
|||
|
|
|
|||
|
|
$this->artisan('billing:migrate-leads-to-rub')->assertOk();
|
|||
|
|
|
|||
|
|
expect($tenant->fresh()->balance_rub)->toBe($balanceAfterFirst);
|
|||
|
|
expect(BalanceTransaction::where('type', BalanceTransaction::TYPE_MIGRATION)->count())->toBe(1);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('skips tenants with balance_leads = 0', function () {
|
|||
|
|
Tenant::factory()->create([
|
|||
|
|
'balance_leads' => 0,
|
|||
|
|
'balance_rub' => '500.00',
|
|||
|
|
]);
|
|||
|
|
|
|||
|
|
$this->artisan('billing:migrate-leads-to-rub')->assertOk();
|
|||
|
|
|
|||
|
|
expect(BalanceTransaction::where('type', BalanceTransaction::TYPE_MIGRATION)->count())->toBe(0);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('aborts if no active tier 1 configured', function () {
|
|||
|
|
PricingTier::query()->update(['is_active' => false]);
|
|||
|
|
Tenant::factory()->create(['balance_leads' => 5]);
|
|||
|
|
|
|||
|
|
$this->artisan('billing:migrate-leads-to-rub')->assertFailed();
|
|||
|
|
});
|