,paths:list,storeEntities:list,rows:Collection, * balances:array, * reserveStandards:array,summary:array{source:int,matched:int,ambiguous:int,unmatched:int,not_ready:int}, * balanceColumnLabel:string,balanceDate:string * } */ public function results(Request $request): array { $filters = $this->filters($request); $platforms = $this->options('store_platform'); $paths = $this->options('receiving_method'); $storeEntities = $this->options('store_entity_name'); $query = StoreReceivingAccount::query(); if ($filters['platform'] !== '') { $query->where('store_platform', $filters['platform']); } if ($filters['withdrawalPath'] !== '') { $query->where('receiving_method', $filters['withdrawalPath']); } if ($filters['storeEntity'] !== '') { $query->where('store_entity_name', $filters['storeEntity']); } if ($filters['keyword'] !== '') { $query->where('store_name', 'like', '%' . addcslashes($filters['keyword'], '%_\\') . '%'); } $today = now()->startOfDay(); $balanceDate = $today->copy()->subDay()->toDateString(); $rows = $query->orderByDesc('id')->get(); $balances = $this->shopBalances->matchesForStores($rows, $balanceDate); $balanceCounts = collect($balances)->countBy( static fn (array $match): string => $match['status'], ); if ($filters['balanceStatus'] !== '') { $rows = $rows->filter( static fn (StoreReceivingAccount $row): bool => ($balances[(int) $row->id]['status'] ?? 'not_ready') === $filters['balanceStatus'], ); } $statusOrder = ['matched' => 0, 'ambiguous' => 1, 'unmatched' => 2, 'not_ready' => 3]; $rows = $rows->sort( static function (StoreReceivingAccount $left, StoreReceivingAccount $right) use ($balances, $statusOrder): int { $leftStatus = $balances[(int) $left->id]['status'] ?? 'not_ready'; $rightStatus = $balances[(int) $right->id]['status'] ?? 'not_ready'; $statusComparison = ($statusOrder[$leftStatus] ?? 99) <=> ($statusOrder[$rightStatus] ?? 99); return $statusComparison !== 0 ? $statusComparison : ((int) $right->id <=> (int) $left->id); }, )->values(); $reserveStandards = $rows->mapWithKeys( static fn (StoreReceivingAccount $row): array => [ (int) $row->id => WithdrawalReserveStandard::amountFor( $row->store_platform, $row->erp_store_name, ), ], )->all(); return [ 'filters' => $filters, 'platforms' => $platforms, 'paths' => $paths, 'storeEntities' => $storeEntities, 'rows' => $rows, 'balances' => $balances, 'reserveStandards' => $reserveStandards, 'summary' => [ 'source' => $this->shopBalances->countForDate($balanceDate), 'matched' => (int) $balanceCounts->get('matched', 0), 'ambiguous' => (int) $balanceCounts->get('ambiguous', 0), 'unmatched' => (int) $balanceCounts->get('unmatched', 0), 'not_ready' => (int) $balanceCounts->get('not_ready', 0), ], 'balanceColumnLabel' => $today->format('n月j日') . '店铺余额', 'balanceDate' => $balanceDate, ]; } /** @return array{platform:string,withdrawalPath:string,storeEntity:string,keyword:string,balanceStatus:string} */ public function filters(Request $request): array { $clean = static fn (mixed $value, int $length = 80): string => mb_substr(trim((string) $value), 0, $length); $balanceStatus = $clean($request->query('balance_status')); if (! in_array($balanceStatus, ['matched', 'unmatched', 'ambiguous', 'not_ready'], true)) { $balanceStatus = ''; } return [ 'platform' => $clean($request->query('platform')), 'withdrawalPath' => $clean($request->query('withdrawal_path')), 'storeEntity' => $clean($request->query('store_entity'), 191), 'keyword' => $clean($request->query('keyword'), 191), 'balanceStatus' => $balanceStatus, ]; } /** @return list */ private function options(string $column): array { return StoreReceivingAccount::query() ->whereNotNull($column) ->where($column, '<>', '') ->distinct() ->orderBy($column) ->pluck($column) ->filter() ->values() ->all(); } }