feat(billing): topup ledger service + POST /api/billing/topup stub (E1)
BillingTopupService кредитует tenants.balance_rub (bcmath) и пишет append-only строку balance_transactions(type='topup'). BillingController + route POST /api/billing/topup под [auth:sanctum, tenant]. MVP-stub: без платёжного шлюза (ЮKassa — post-Б-1). Sprint 2 Plan C, audit E1 (backend). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\User;
|
||||
use App\Services\Billing\BillingTopupService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* Биллинг тенанта — кошелёк, транзакции, счета, пополнение (audit E1/E3).
|
||||
*
|
||||
* Все эндпоинты под middleware [auth:sanctum, tenant] (RLS-контекст).
|
||||
* Отдельно от TenantChargesController (lead_charges ledger) и
|
||||
* AdminBillingController (SaaS-уровневые агрегаты).
|
||||
*
|
||||
* E1: POST /api/billing/topup — MVP-stub пополнения (без платёжного шлюза).
|
||||
* E3: GET wallet/transactions/invoices — данные для BillingView Overview.
|
||||
*/
|
||||
class BillingController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly BillingTopupService $topupService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* POST /api/billing/topup — пополнить рублёвый баланс.
|
||||
*
|
||||
* MVP-stub: кредитует баланс немедленно (без ЮKassa — реальная оплата
|
||||
* post-Б-1). Записывает append-only строку balance_transactions(topup).
|
||||
*/
|
||||
public function topup(Request $request): JsonResponse
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'amount_rub' => ['required', 'numeric', 'min:100', 'max:1000000', 'decimal:0,2'],
|
||||
]);
|
||||
|
||||
/** @var User $user */
|
||||
$user = $request->user();
|
||||
|
||||
// Нормализуем в DECIMAL-строку scale 2 для bcmath (НЕ float).
|
||||
$amountRub = bcadd((string) $validated['amount_rub'], '0', 2);
|
||||
|
||||
$tx = $this->topupService->topup((int) $user->tenant_id, $amountRub, (int) $user->id);
|
||||
|
||||
return response()->json([
|
||||
'transaction' => [
|
||||
'id' => $tx->id,
|
||||
'type' => $tx->type,
|
||||
'amount_rub' => $tx->amount_rub,
|
||||
'balance_rub_after' => $tx->balance_rub_after,
|
||||
'created_at' => $tx->created_at,
|
||||
],
|
||||
'balance_rub' => $tx->balance_rub_after,
|
||||
], 201);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user