104 lines
3.3 KiB
PHP
104 lines
3.3 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
use App\Jobs\Sales\SalesProspectsAdvanceJob;
|
||
|
|
use App\Models\SalesProspect;
|
||
|
|
use App\Models\SalesUser;
|
||
|
|
use App\Models\Tenant;
|
||
|
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||
|
|
use Illuminate\Support\Facades\DB;
|
||
|
|
|
||
|
|
uses(DatabaseTransactions::class);
|
||
|
|
|
||
|
|
function adv_user(): SalesUser
|
||
|
|
{
|
||
|
|
return SalesUser::create([
|
||
|
|
'name' => 'A '.uniqid(), 'email' => 'adv'.uniqid().'@s.local',
|
||
|
|
'password' => bcrypt('x'), 'role' => 'manager', 'is_active' => true,
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
function adv_prospect(SalesUser $u, ?int $tenantId, string $stage): SalesProspect
|
||
|
|
{
|
||
|
|
return SalesProspect::factory()->for($u, 'salesUser')->create([
|
||
|
|
'stage' => $stage, 'linked_tenant_id' => $tenantId,
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
function adv_txn(int $tenantId, string $type, string $amountRub): void
|
||
|
|
{
|
||
|
|
DB::table('balance_transactions')->insert([
|
||
|
|
'tenant_id' => $tenantId, 'type' => $type, 'amount_rub' => $amountRub,
|
||
|
|
'amount_leads' => 0, 'balance_rub_after' => $amountRub, 'description' => 'test',
|
||
|
|
'created_at' => now(),
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
test('пополнения ≥ 30000 → user', function () {
|
||
|
|
$u = adv_user();
|
||
|
|
$t = Tenant::factory()->create();
|
||
|
|
$p = adv_prospect($u, $t->id, 'registered');
|
||
|
|
adv_txn($t->id, 'topup', '30000');
|
||
|
|
|
||
|
|
(new SalesProspectsAdvanceJob)->handle();
|
||
|
|
|
||
|
|
expect(SalesProspect::find($p->id)->stage)->toBe('user');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('есть реальное пополнение < 30000 → topped_up', function () {
|
||
|
|
$u = adv_user();
|
||
|
|
$t = Tenant::factory()->create();
|
||
|
|
$p = adv_prospect($u, $t->id, 'registered');
|
||
|
|
adv_txn($t->id, 'topup', '5000');
|
||
|
|
|
||
|
|
(new SalesProspectsAdvanceJob)->handle();
|
||
|
|
|
||
|
|
expect(SalesProspect::find($p->id)->stage)->toBe('topped_up');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('нет пополнений, но есть расход (бонус пошёл в дело) → testing', function () {
|
||
|
|
$u = adv_user();
|
||
|
|
$t = Tenant::factory()->create();
|
||
|
|
$p = adv_prospect($u, $t->id, 'registered');
|
||
|
|
adv_txn($t->id, 'lead_charge', '20');
|
||
|
|
|
||
|
|
(new SalesProspectsAdvanceJob)->handle();
|
||
|
|
|
||
|
|
expect(SalesProspect::find($p->id)->stage)->toBe('testing');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('нет активности → остаётся registered', function () {
|
||
|
|
$u = adv_user();
|
||
|
|
$t = Tenant::factory()->create();
|
||
|
|
$p = adv_prospect($u, $t->id, 'registered');
|
||
|
|
|
||
|
|
(new SalesProspectsAdvanceJob)->handle();
|
||
|
|
|
||
|
|
expect(SalesProspect::find($p->id)->stage)->toBe('registered');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('карточку без linked_tenant_id и ручные стадии (rejected) джоба НЕ трогает', function () {
|
||
|
|
$u = adv_user();
|
||
|
|
$t = Tenant::factory()->create();
|
||
|
|
$rejected = adv_prospect($u, $t->id, 'rejected'); // linked, но отказ
|
||
|
|
$newNoLink = adv_prospect($u, null, 'new');
|
||
|
|
adv_txn($t->id, 'topup', '50000');
|
||
|
|
|
||
|
|
(new SalesProspectsAdvanceJob)->handle();
|
||
|
|
|
||
|
|
expect(SalesProspect::find($rejected->id)->stage)->toBe('rejected');
|
||
|
|
expect(SalesProspect::find($newNoLink->id)->stage)->toBe('new');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('пользователь без новых денег не откатывается назад', function () {
|
||
|
|
$u = adv_user();
|
||
|
|
$t = Tenant::factory()->create();
|
||
|
|
$p = adv_prospect($u, $t->id, 'user');
|
||
|
|
adv_txn($t->id, 'topup', '35000');
|
||
|
|
|
||
|
|
(new SalesProspectsAdvanceJob)->handle();
|
||
|
|
|
||
|
|
expect(SalesProspect::find($p->id)->stage)->toBe('user');
|
||
|
|
});
|