79 lines
3.3 KiB
PHP
79 lines
3.3 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
use App\Models\AdWallet;
|
||
|
|
use App\Models\Tenant;
|
||
|
|
use App\Models\User;
|
||
|
|
use App\Services\Advertising\AdWalletService;
|
||
|
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* GET /api/advertising/wallet/transactions — история операций рекламного кошелька.
|
||
|
|
*
|
||
|
|
* Приёмка 03.08.2026: на экране кошелька вместо истории стояло «появится позже», и клиент
|
||
|
|
* не мог объяснить себе ни одну заморозку. Ручки списка не было вовсе.
|
||
|
|
*
|
||
|
|
* Сторож держит два правила: клиент видит СВОИ движения человеческими словами и НЕ видит
|
||
|
|
* чужие — рекламные деньги идут по тем же путям, что и остальные, и разделение клиентов
|
||
|
|
* здесь так же обязательно.
|
||
|
|
*/
|
||
|
|
uses(DatabaseTransactions::class);
|
||
|
|
|
||
|
|
beforeEach(function () {
|
||
|
|
$this->tenant = Tenant::factory()->create();
|
||
|
|
$this->user = User::factory()->create(['tenant_id' => $this->tenant->id]);
|
||
|
|
$this->actingAs($this->user);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('отдаёт движения кошелька, свежие сверху', function () {
|
||
|
|
AdWallet::create(['tenant_id' => $this->tenant->id, 'balance_rub' => '0.00', 'frozen_rub' => '0.00']);
|
||
|
|
$svc = app(AdWalletService::class);
|
||
|
|
|
||
|
|
$svc->topup($this->tenant->id, '10000.00', 'yandex', 'Пополнение по счёту №12');
|
||
|
|
$svc->freeze($this->tenant->id, 'yandex', 'campaign', 6, '3333.36');
|
||
|
|
$svc->release($this->tenant->id, 'yandex', 'campaign', 6);
|
||
|
|
|
||
|
|
$response = $this->getJson('/api/advertising/wallet/transactions');
|
||
|
|
|
||
|
|
$response->assertOk();
|
||
|
|
$items = $response->json('items');
|
||
|
|
|
||
|
|
expect($items)->toHaveCount(3);
|
||
|
|
// Свежие сверху — клиент читает историю сверху вниз.
|
||
|
|
expect($items[0]['type'])->toBe('release')
|
||
|
|
->and($items[1]['type'])->toBe('freeze')
|
||
|
|
->and($items[2]['type'])->toBe('topup');
|
||
|
|
|
||
|
|
expect($items[1]['amount_rub'])->toBe('-3333.36')
|
||
|
|
->and($items[1]['description'])->toContain('6')
|
||
|
|
->and($items[0]['amount_rub'])->toBe('3333.36');
|
||
|
|
|
||
|
|
// Каждое движение подписано человеческими словами, а не кодом типа.
|
||
|
|
expect($items[1])->toHaveKey('title')
|
||
|
|
->and($items[1]['title'])->not->toBe('freeze');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('чужие движения не отдаёт', function () {
|
||
|
|
$chuzhoy = Tenant::factory()->create();
|
||
|
|
AdWallet::create(['tenant_id' => $chuzhoy->id, 'balance_rub' => '0.00', 'frozen_rub' => '0.00']);
|
||
|
|
app(AdWalletService::class)->topup($chuzhoy->id, '99999.00', 'yandex', 'Чужое пополнение');
|
||
|
|
|
||
|
|
$response = $this->getJson('/api/advertising/wallet/transactions');
|
||
|
|
|
||
|
|
$response->assertOk();
|
||
|
|
expect($response->json('items'))->toBe([]);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('пустая история — пустой список, а не ошибка', function () {
|
||
|
|
$this->getJson('/api/advertising/wallet/transactions')
|
||
|
|
->assertOk()
|
||
|
|
->assertJson(['items' => []]);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('без входа не отдаёт ничего', function () {
|
||
|
|
auth()->logout();
|
||
|
|
|
||
|
|
$this->getJson('/api/advertising/wallet/transactions')->assertStatus(401);
|
||
|
|
});
|