fix(funds): 加固转账冲正、结算收付幂等与坏账核销
Some checks failed
lotterLaravel CI / test (push) Has been cancelled
lotterLaravel E2E / e2e-api (push) Has been cancelled

- 转入 main_site_timeout 等不可冲正场景直接拒绝,避免假结案
- payment_records / settlement_adjustments 增加 partial unique 索引
- 坏账核销行锁 + meta 幂等回放;补差单记录 result_bill_id
- 新增 FundOperationsHardeningTest 覆盖关键路径
This commit is contained in:
2026-06-26 15:19:17 +08:00
parent 3f04b4ebe3
commit 7ec8f4c5a2
8 changed files with 535 additions and 104 deletions

View File

@@ -32,9 +32,7 @@ final class AdminTransferOrderCapabilities
$canWrite = self::canWriteWallet($admin);
return [
'can_reverse' => $canWrite
&& $order->status === 'pending_reconcile'
&& ($order->direction === 'out' || $transferService->isEligibleForTransferInReverse($order)),
'can_reverse' => $canWrite && $transferService->isEligibleForReverse($order),
'can_complete_credit' => $canWrite
&& $order->direction === 'in'
&& $order->status === 'pending_reconcile'

View File

@@ -0,0 +1,26 @@
<?php
namespace App\Support;
use Illuminate\Database\QueryException;
/** 识别数据库唯一约束冲突PostgreSQL / SQLite / MySQL。 */
final class DatabaseUniqueViolation
{
public static function matches(QueryException $e): bool
{
$sqlState = (string) $e->getCode();
$errorInfo = $e->errorInfo ?? null;
$driverCode = is_array($errorInfo) ? (int) ($errorInfo[1] ?? 0) : 0;
if ($sqlState === '23505' || $sqlState === '23000' || $sqlState === '19') {
return true;
}
if ($driverCode === 19 || $driverCode === 1062) {
return true;
}
return stripos($e->getMessage(), 'unique') !== false;
}
}