$items */ public function createPendingBatch(Draw $draw, AdminUser $admin, array $items): DrawResultBatch { return DB::transaction(function () use ($draw, $admin, $items): DrawResultBatch { /** @var Draw $locked */ $locked = Draw::query()->whereKey($draw->id)->lockForUpdate()->firstOrFail(); if (! in_array($locked->status, [DrawStatus::Closed->value, DrawStatus::Review->value], true)) { throw new \RuntimeException('draw_not_editable'); } if ($locked->settle_version > 0 || $locked->status === DrawStatus::Settled->value) { throw new \RuntimeException('draw_already_settled'); } if (DrawResultBatch::query() ->where('draw_id', $locked->id) ->where('status', DrawResultBatchStatus::PendingReview->value) ->exists()) { throw new \RuntimeException('draw_pending_result_batch_exists'); } $nextVersion = max(1, (int) $locked->current_result_version + 1); $batch = DrawResultBatch::query()->create([ 'draw_id' => $locked->id, 'result_version' => $nextVersion, 'source_type' => DrawResultSourceType::Manual->value, 'rng_seed_hash' => null, 'raw_seed_encrypted' => null, 'status' => DrawResultBatchStatus::PendingReview->value, 'created_by' => $admin->id, 'confirmed_by' => null, 'confirmed_at' => null, ]); foreach ($this->sortByLayout($items) as $item) { $number = (string) $item['number_4d']; DrawResultItem::query()->create([ 'draw_id' => $locked->id, 'result_batch_id' => $batch->id, 'prize_type' => $item['prize_type'], 'prize_index' => (int) $item['prize_index'], 'number_4d' => $number, 'suffix_3d' => substr($number, -3), 'suffix_2d' => substr($number, -2), 'head_digit' => (int) substr($number, 0, 1), 'tail_digit' => (int) substr($number, 3, 1), ]); } $locked->forceFill([ 'status' => DrawStatus::Review->value, 'result_source' => DrawResultSourceType::Manual->value, ])->save(); return $batch->fresh(['items']); }); } /** * @param list $items * @return list */ private function sortByLayout(array $items): array { $order = []; foreach (DrawPrizeLayout::slots() as $i => $slot) { $order[$slot['prize_type'].':'.$slot['prize_index']] = $i; } usort($items, fn (array $a, array $b): int => ($order[$a['prize_type'].':'.$a['prize_index']] ?? 99) <=> ($order[$b['prize_type'].':'.$b['prize_index']] ?? 99)); return $items; } }