* } */ public function forBill(object $bill): array { if ((string) $bill->bill_type !== 'agent' || (string) $bill->owner_type !== 'agent') { return ['total' => 0, 'items' => []]; } $ownerId = (int) $bill->owner_id; $periodId = (int) $bill->settlement_period_id; if ($ownerId <= 0 || $periodId <= 0) { return ['total' => 0, 'items' => []]; } $owner = AgentNode::query()->find($ownerId); if ($owner === null) { return ['total' => 0, 'items' => []]; } $descendantIds = AgentNode::query() ->where('admin_site_id', (int) $owner->admin_site_id) ->where('id', '!=', $ownerId) ->where('path', 'like', $owner->path.'%') ->pluck('id') ->map(static fn ($id): int => (int) $id) ->all(); if ($descendantIds === []) { return ['total' => 0, 'items' => []]; } $rows = DB::table('settlement_bills') ->where('settlement_period_id', $periodId) ->where('bill_type', 'agent') ->where('owner_type', 'agent') ->whereIn('owner_id', $descendantIds) ->orderBy('owner_id') ->get(['owner_id', 'meta_json']); if ($rows->isEmpty()) { return ['total' => 0, 'items' => []]; } $agentIds = $rows->pluck('owner_id')->map(static fn ($id): int => (int) $id)->all(); $agents = $this->partyEnrichment->loadAgents($agentIds); $items = []; $total = 0; foreach ($rows as $row) { $shareProfit = $this->shareProfitFromMeta($row->meta_json ?? null); if ($shareProfit === 0) { continue; } $agentId = (int) $row->owner_id; $items[] = [ 'owner_id' => $agentId, 'owner_label' => $this->partyEnrichment->formatAgent($agents->get($agentId), $agentId), 'share_profit' => $shareProfit, ]; $total += $shareProfit; } usort($items, static fn (array $a, array $b): int => $b['share_profit'] <=> $a['share_profit'] ?: $a['owner_label'] <=> $b['owner_label']); return [ 'total' => $total, 'items' => $items, ]; } private function shareProfitFromMeta(mixed $metaJson): int { if ($metaJson === null || $metaJson === '') { return 0; } $decoded = is_string($metaJson) ? json_decode($metaJson, true) : $metaJson; return is_array($decoded) ? (int) ($decoded['share_profit'] ?? 0) : 0; } }