Files
lotteryLaravel/app/Services/Jackpot/JackpotPoolAdjustmentService.php
kang c8c90e3e94 feat: 增强奖池与钱包管理功能
更新 AdminJackpotPoolUpdateController 校验规则,禁止传入 current_amount。
优化 AdminRiskPoolManualStatusController:更新奖池状态后同步 Redis 状态。
在 TransferOrderReconcileController 中新增 completeCredit 方法,用于处理卡住的转账订单对账。
调整 TransferOrderListController:优化转账订单处理条件。
在 TicketItemsIndexController 中实现支持时区的日期筛选,提升日期处理准确性。
扩展 JackpotPool 模型,新增 adjustments 关联关系。
改进票据与钱包相关服务中的错误处理和事务管理。
2026-05-26 14:58:41 +08:00

96 lines
3.0 KiB
PHP

<?php
namespace App\Services\Jackpot;
use App\Models\AdminUser;
use App\Models\JackpotPool;
use App\Models\JackpotPoolAdjustment;
use App\Services\AuditLogger;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
final class JackpotPoolAdjustmentService
{
public function apply(
JackpotPool $pool,
AdminUser $admin,
int $amountDelta,
string $reason,
?Request $request = null,
): JackpotPoolAdjustment {
if ($amountDelta === 0) {
throw new \RuntimeException('adjustment_delta_zero');
}
$reason = trim($reason);
if ($reason === '') {
throw new \RuntimeException('adjustment_reason_required');
}
return DB::transaction(function () use ($pool, $admin, $amountDelta, $reason, $request): JackpotPoolAdjustment {
/** @var JackpotPool $locked */
$locked = JackpotPool::query()->whereKey($pool->id)->lockForUpdate()->firstOrFail();
$before = (int) $locked->current_amount;
$after = $before + $amountDelta;
if ($after < 0) {
throw new \RuntimeException('adjustment_would_make_balance_negative');
}
$adjustment = JackpotPoolAdjustment::query()->create([
'adjustment_no' => $this->newAdjustmentNo(),
'jackpot_pool_id' => $locked->id,
'admin_user_id' => $admin->id,
'amount_delta' => $amountDelta,
'balance_before' => $before,
'balance_after' => $after,
'reason' => $reason,
]);
$locked->forceFill(['current_amount' => $after])->save();
$snapshot = [
'currency_code' => $locked->currency_code,
'amount_delta' => $amountDelta,
'balance_before' => $before,
'balance_after' => $after,
'reason' => $reason,
'adjustment_no' => $adjustment->adjustment_no,
];
if ($request !== null) {
AuditLogger::recordFromRequest(
$request,
AuditLogger::OPERATOR_ADMIN,
$admin->id,
'jackpot',
'adjust_balance',
'jackpot_pool',
(string) $locked->id,
['current_amount' => $before],
$snapshot,
);
} else {
AuditLogger::record(
AuditLogger::OPERATOR_ADMIN,
$admin->id,
'jackpot',
'adjust_balance',
'jackpot_pool',
(string) $locked->id,
['current_amount' => $before],
$snapshot,
);
}
return $adjustment->fresh(['adminUser']);
});
}
private function newAdjustmentNo(): string
{
return 'JA'.now()->format('YmdHis').Str::upper(Str::random(6));
}
}