fix(billing): topup save() rationale comment + cross-tenant test (Task 1 review)
Code-quality review fixups: документирующий комментарий про безопасность Eloquent save() для bcmath-строки (расхождение с LedgerService raw-update); cross-tenant isolation тест на /api/billing/topup; balance_rub_after в assertDatabaseHas. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -41,6 +41,10 @@ final class BillingTopupService
|
||||
// bcadd — DECIMAL-точность, НЕ PHP float (паттерн LedgerService).
|
||||
$newBalanceRub = bcadd((string) $tenant->balance_rub, $amountRub, 2);
|
||||
|
||||
// Eloquent decimal:2 cast сохраняет bcmath-строку без потери точности
|
||||
// при save() (в отличие от decrement(), который требует float|int —
|
||||
// именно поэтому LedgerService использует raw DB::table()->update();
|
||||
// здесь же присваивание уже посчитанной строки через модель безопасно).
|
||||
$tenant->balance_rub = $newBalanceRub;
|
||||
$tenant->save();
|
||||
|
||||
|
||||
@@ -591,7 +591,7 @@ parameters:
|
||||
-
|
||||
message: '#^Call to an undefined method Pest\\PendingCalls\\TestCall\:\:postJson\(\)\.$#'
|
||||
identifier: method.notFound
|
||||
count: 7
|
||||
count: 8
|
||||
path: tests/Feature/Billing/TopupControllerTest.php
|
||||
|
||||
-
|
||||
|
||||
@@ -33,6 +33,7 @@ test('POST /api/billing/topup пишет строку balance_transactions с us
|
||||
'user_id' => $this->user->id,
|
||||
'type' => 'topup',
|
||||
'amount_rub' => '100.00',
|
||||
'balance_rub_after' => '600.00',
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -44,6 +45,16 @@ test('POST /api/billing/topup использует bcmath-точность', fun
|
||||
expect((string) $this->tenant->fresh()->balance_rub)->toBe('100.30');
|
||||
});
|
||||
|
||||
test('POST /api/billing/topup не затрагивает баланс чужого тенанта', function () {
|
||||
$otherTenant = Tenant::factory()->create(['balance_rub' => '777.00']);
|
||||
|
||||
$this->postJson('/api/billing/topup', ['amount_rub' => 100])->assertStatus(201);
|
||||
|
||||
// Топап эндпоинт не принимает tenant_id — резолвит из auth-пользователя;
|
||||
// баланс чужого тенанта неприкосновенен (defense-in-depth, паттерн проекта).
|
||||
expect((string) $otherTenant->fresh()->balance_rub)->toBe('777.00');
|
||||
});
|
||||
|
||||
test('POST /api/billing/topup отклоняет сумму ниже минимума 100 ₽', function () {
|
||||
$this->postJson('/api/billing/topup', ['amount_rub' => 50])
|
||||
->assertStatus(422)
|
||||
|
||||
Reference in New Issue
Block a user