Files
lotteryLaravel/app/Services/Settlement/DrawSettlementStartService.php
wchino 15bd997c4e
Some checks failed
lotterLaravel CI / test (push) Has been cancelled
lotterLaravel E2E / e2e-api (push) Has been cancelled
feat(core): harden sessions settlement and credit activity
2026-07-22 20:53:43 +08:00

58 lines
1.7 KiB
PHP

<?php
namespace App\Services\Settlement;
use App\Models\Draw;
use App\Lottery\DrawStatus;
use App\Models\DrawResultBatch;
use Illuminate\Support\Facades\DB;
use App\Lottery\DrawResultBatchStatus;
/**
* 将期号推进到可结算状态。
*
* 冷静期内的人工操作只跳过当前期剩余的核错窗口,不修改全局冷静期配置。
*/
final class DrawSettlementStartService
{
/**
* @return array{draw: Draw, cooldown_skipped: bool}
*/
public function start(Draw $draw): array
{
return DB::transaction(function () use ($draw): array {
/** @var Draw $locked */
$locked = Draw::query()->whereKey($draw->id)->lockForUpdate()->firstOrFail();
if (! in_array($locked->status, [
DrawStatus::Cooldown->value,
DrawStatus::Settling->value,
], true)) {
throw new \RuntimeException('draw_not_ready_for_settlement');
}
$hasPublishedResult = DrawResultBatch::query()
->where('draw_id', $locked->id)
->where('status', DrawResultBatchStatus::Published->value)
->exists();
if (! $hasPublishedResult) {
throw new \RuntimeException('draw_result_not_published');
}
$cooldownSkipped = $locked->status === DrawStatus::Cooldown->value;
if ($cooldownSkipped) {
$locked->forceFill([
'status' => DrawStatus::Settling->value,
'cooling_end_time' => now(),
])->save();
}
return [
'draw' => $locked->fresh(),
'cooldown_skipped' => $cooldownSkipped,
];
});
}
}