lotteryAdmin(); abort_if($admin === null, 401); $p = AdminApiList::readPaging($request, 50, 200); $paginator = $reconcile_job->items() ->orderBy('id') ->paginate($p['perPage'], ['*'], 'page', $p['page']); $transferNos = collect($paginator->items()) ->map(fn (ReconcileItem $item) => $item->side_a_ref) ->filter(fn ($value) => is_string($value) && $value !== '') ->values() ->all(); $transferOrders = $transferNos === [] ? collect() : TransferOrder::query() ->with(['player:id,site_code,site_player_id']) ->whereIn('transfer_no', $transferNos) ->get() ->keyBy('transfer_no'); return AdminApiList::jsonWith($paginator, function (ReconcileItem $r) use ($transferOrders, $admin): array { $transferNo = (string) ($r->side_a_ref ?? ''); /** @var TransferOrder|null $order */ $order = $transferNo !== '' ? $transferOrders->get($transferNo) : null; $resolvedStatuses = ['success', 'reversed', 'manually_processed']; $currentStatus = $order?->status; $isResolved = $r->resolved_at !== null || in_array($currentStatus, $resolvedStatuses, true); $capabilities = $order instanceof TransferOrder ? AdminTransferOrderCapabilities::forOrder( $order, $admin instanceof AdminUser ? $admin : null, $this->transferService, ) : [ 'can_reverse' => false, 'can_complete_credit' => false, 'can_manually_process' => false, ]; $mainSiteCheck = $this->resolveMainSiteCheck($order); return [ 'id' => (int) $r->id, 'side_a_ref' => $r->side_a_ref, 'side_b_ref' => $r->side_b_ref, 'external_ref_no' => $order?->external_ref_no, 'difference_amount' => (int) $r->difference_amount, 'status' => $r->status, 'resolved_at' => $r->resolved_at?->toIso8601String(), 'is_resolved' => $isResolved, 'current_transfer_status' => $currentStatus, 'transfer_direction' => $order?->direction, 'transfer_fail_reason' => $order?->fail_reason, 'main_site_check' => $mainSiteCheck['status'], 'main_site_check_message' => $mainSiteCheck['message'], 'main_site_external_ref_no' => $mainSiteCheck['external_ref_no'], ...$capabilities, 'created_at' => $r->created_at?->toIso8601String(), ]; }, [ 'job_id' => (int) $reconcile_job->id, 'job_no' => $reconcile_job->job_no, ]); } /** * @return array{status: string, message: ?string, external_ref_no: ?string} */ private function resolveMainSiteCheck(?TransferOrder $order): array { if ($order === null || $order->player === null) { return [ 'status' => MainSiteWalletIdempotentProbeResult::STATUS_SKIPPED, 'message' => null, 'external_ref_no' => null, ]; } if (trim((string) $order->idempotent_key) === '') { return [ 'status' => MainSiteWalletIdempotentProbeResult::STATUS_SKIPPED, 'message' => null, 'external_ref_no' => null, ]; } $shouldProbe = trim((string) $order->external_ref_no) !== '' || $order->status === 'success' || ( $order->direction === 'in' && $order->status === 'pending_reconcile' && $order->fail_reason === 'lottery_credit_failed' ); if (! $shouldProbe) { return [ 'status' => MainSiteWalletIdempotentProbeResult::STATUS_SKIPPED, 'message' => null, 'external_ref_no' => null, ]; } $probe = $this->mainSiteProbeClient->probe($order->player, (string) $order->idempotent_key); return [ 'status' => $probe->status, 'message' => $probe->message, 'external_ref_no' => $probe->externalRefNo ?? $order->external_ref_no, ]; } }