Files
portal/app/tests/Feature/Sales/SalesModelsTest.php
T

182 lines
6.9 KiB
PHP
Raw Normal View History

<?php
declare(strict_types=1);
use App\Models\SalesAttachmentRequest;
use App\Models\SalesClientAssignment;
use App\Models\SalesPayout;
use App\Models\SalesTariff;
use App\Models\SalesUser;
use App\Models\Tenant;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\QueryException;
use Illuminate\Foundation\Testing\DatabaseTransactions;
/**
* Smoke-тесты Eloquent-моделей портала продаж.
* Проверяют: создание записей, каsты, связи, вспомогательные методы.
*
* Изоляция: DatabaseTransactions — каждый тест оборачивается в транзакцию
* и откатывается, не оставляя строк в liderra_testing.
*
* Используем DEFAULT connection (pgsql → liderra_testing в тестах).
* sales_* таблицы созданы Task 0.1 (migration 2026_07_01_100000_create_sales_portal_tables.php).
*/
uses(DatabaseTransactions::class);
// ── helpers ────────────────────────────────────────────────────────────────
function makeSalesTariff(array $attrs = []): SalesTariff
{
return SalesTariff::create(array_merge([
'name' => 'Test tariff '.uniqid(),
'kind' => 'topup_step',
'params' => ['step' => 1000, 'bonus' => 100],
'is_active' => true,
], $attrs));
}
function makeSalesUser(array $attrs = []): SalesUser
{
return SalesUser::create(array_merge([
'name' => 'Manager '.uniqid(),
'email' => 'mgr'.uniqid().'@test.local',
'password' => bcrypt('secret'),
'role' => 'manager',
], $attrs));
}
// ── 1. SalesTariff ─────────────────────────────────────────────────────────
test('SalesTariff можно создать и params отдаётся массивом', function () {
$tariff = makeSalesTariff([
'params' => ['step' => 5000, 'bonus' => 500],
]);
expect($tariff->id)->toBeInt()
->and($tariff->name)->toStartWith('Test tariff')
->and($tariff->kind)->toBe('topup_step')
->and($tariff->params)->toBeArray()
->and($tariff->params['step'])->toBe(5000)
->and($tariff->is_active)->toBeTrue();
});
// ── 2. SalesUser ───────────────────────────────────────────────────────────
test('SalesUser создаётся с role=manager и current_tariff_id', function () {
$tariff = makeSalesTariff();
$user = makeSalesUser([
'role' => 'manager',
'current_tariff_id' => $tariff->id,
'base_salary_rub' => '50000.00',
]);
expect($user->id)->toBeInt()
->and($user->role)->toBe('manager')
->and($user->current_tariff_id)->toBe($tariff->id)
->and($user->fresh()->is_active)->toBeTrue(); // DB default=TRUE, fresh() синхронизирует
});
test('SalesUser::isHead() верен для role=head и false для role=manager', function () {
$head = makeSalesUser(['role' => 'head']);
$manager = makeSalesUser(['role' => 'manager']);
expect($head->isHead())->toBeTrue()
->and($manager->isHead())->toBeFalse();
});
test('SalesUser is_active приходит булевым', function () {
$user = makeSalesUser(['is_active' => true]);
expect($user->is_active)->toBeBool()->toBeTrue();
});
// ── 3. SalesClientAssignment ───────────────────────────────────────────────
test('SalesClientAssignment связывает пользователя с тенантом и tariff_params — массив', function () {
$tariff = makeSalesTariff(['kind' => 'percent_oborot', 'params' => ['percent' => 5]]);
$user = makeSalesUser(['current_tariff_id' => $tariff->id]);
$tenant = Tenant::factory()->create(); // реальный тенант (FK tenants.id)
$assignment = SalesClientAssignment::create([
'sales_user_id' => $user->id,
'tenant_id' => $tenant->id,
'tariff_id' => $tariff->id,
'tariff_kind' => $tariff->kind,
'tariff_params' => ['percent' => 5],
'assigned_at' => now(),
]);
expect($assignment->id)->toBeInt()
->and($assignment->tariff_params)->toBeArray()
->and($assignment->tariff_params['percent'])->toBe(5)
->and($assignment->assigned_at)->toBeInstanceOf(Carbon::class);
});
test('SalesUser->assignments() возвращает HasMany-коллекцию', function () {
$user = makeSalesUser();
$tenant = Tenant::factory()->create();
SalesClientAssignment::create([
'sales_user_id' => $user->id,
'tenant_id' => $tenant->id,
'tariff_params' => [],
'assigned_at' => now(),
]);
$relation = $user->assignments();
expect($relation)->toBeInstanceOf(HasMany::class);
$collection = $user->assignments;
expect($collection)->toHaveCount(1)
->and($collection->first())->toBeInstanceOf(SalesClientAssignment::class);
});
// ── 4. SalesAttachmentRequest ──────────────────────────────────────────────
test('SalesAttachmentRequest создаётся со статусом pending', function () {
$user = makeSalesUser();
$req = SalesAttachmentRequest::create([
'sales_user_id' => $user->id,
'login_input' => 'client@example.com',
'status' => 'pending',
]);
expect($req->id)->toBeInt()
->and($req->status)->toBe('pending')
->and($req->decided_at)->toBeNull();
});
// ── 5. SalesPayout ─────────────────────────────────────────────────────────
test('SalesPayout создаётся, amount_rub — decimal, paid_on — date', function () {
$user = makeSalesUser();
$payout = SalesPayout::create([
'sales_user_id' => $user->id,
'amount_rub' => '12500.50',
'paid_on' => today(),
'created_by' => $user->id,
]);
expect($payout->id)->toBeInt()
->and((float) $payout->amount_rub)->toBe(12500.50)
->and($payout->paid_on)->toBeInstanceOf(Carbon::class);
});
test('SalesPayout append-only: UPDATE бросает исключение', function () {
$user = makeSalesUser();
$payout = SalesPayout::create([
'sales_user_id' => $user->id,
'amount_rub' => '100.00',
'paid_on' => today(),
'created_by' => $user->id,
]);
expect(fn () => $payout->update(['amount_rub' => '999.00']))
->toThrow(QueryException::class);
});