diff --git a/modules/EcommerceFinance/Repositories/GoodsProfitAfsRepository.php b/modules/EcommerceFinance/Repositories/GoodsProfitAfsRepository.php index dcdee067..198e4fcc 100644 --- a/modules/EcommerceFinance/Repositories/GoodsProfitAfsRepository.php +++ b/modules/EcommerceFinance/Repositories/GoodsProfitAfsRepository.php @@ -86,7 +86,33 @@ class GoodsProfitAfsRepository /** @param array $filters */ public function covers(array $filters): bool { - return $this->ready() && $this->filtered($filters, $this->fieldColumns())->limit(1)->exists(); + if (! $this->ready()) { + return false; + } + + $columns = $this->fieldColumns(); + $orderNo = trim((string) ($filters['order_no'] ?? '')); + + // 单号查询走各自列的索引,避免 undefined2 OR undefined1 触发全表扫描。 + if ($orderNo !== '') { + foreach (['online_order_no', 'internal_order_no'] as $field) { + if (! isset($columns[$field])) { + continue; + } + + $query = $this->connection()->table(self::MAIN_TABLE) + ->where($columns[$field], 'like', $orderNo . '%'); + $this->applyDateRange($query, $filters, $columns); + + if ($query->limit(1)->exists()) { + return true; + } + } + + return false; + } + + return $this->filtered($filters, $columns)->limit(1)->exists(); } /** @@ -100,6 +126,11 @@ class GoodsProfitAfsRepository $columns = $this->fieldColumns(); $select = array_values(array_unique(array_merge(['id'], array_values($columns)))); $orderColumn = $columns['order_time'] ?? null; + $orderNo = trim((string) ($filters['order_no'] ?? '')); + + if ($orderNo !== '') { + return $this->paginateByOrderNumber($orderNo, $filters, $columns, $select, $page, $limit); + } $query = $this->filtered($filters, $columns)->select($select); @@ -133,6 +164,75 @@ class GoodsProfitAfsRepository ]; } + /** + * 单号查询:分别走 online/internal 两个索引,合并后在 PHP 排序分页。 + * + * @param array $filters + * @param array $columns + * @param list $select + * @return array{rows:list>,has_more:bool} + */ + private function paginateByOrderNumber( + string $orderNo, + array $filters, + array $columns, + array $select, + int $page, + int $limit, + ): array { + $records = []; + $cap = max($limit * 4, 400); + + foreach (['online_order_no', 'internal_order_no'] as $field) { + if (! isset($columns[$field])) { + continue; + } + + $query = $this->connection()->table(self::MAIN_TABLE) + ->select($select) + ->where($columns[$field], 'like', $orderNo . '%'); + $this->applyDateRange($query, $filters, $columns); + + foreach ($query->limit($cap)->get() as $record) { + $records[(int) $record->id] = $record; + } + } + + $timeColumn = $columns['order_time'] ?? null; + usort($records, static function ($left, $right) use ($timeColumn): int { + $leftTime = $timeColumn !== null ? strtotime(str_replace('/', '-', (string) ($left->{$timeColumn} ?? ''))) : false; + $rightTime = $timeColumn !== null ? strtotime(str_replace('/', '-', (string) ($right->{$timeColumn} ?? ''))) : false; + + return [$rightTime ?: 0, (int) $right->id] <=> [$leftTime ?: 0, (int) $left->id]; + }); + + $numberKeys = array_flip((array) config('order_after_sales_cost.number_keys', [])); + $rows = []; + + foreach ($records as $record) { + $row = []; + + foreach ($columns as $field => $column) { + $value = $record->{$column} ?? null; + + if (isset($numberKeys[$field])) { + $value = $value === null ? null : (float) $value; + } + + $row[$field] = is_string($value) ? trim($value) : $value; + } + + $rows[] = $row; + } + + $offset = ($page - 1) * $limit; + + return [ + 'rows' => array_slice($rows, $offset, $limit), + 'has_more' => count($rows) > $offset + $limit, + ]; + } + /** * @param array $filters * @param array $columns @@ -189,6 +289,30 @@ class GoodsProfitAfsRepository return $query; } + /** + * @param array $filters + * @param array $columns + */ + private function applyDateRange(\Illuminate\Database\Query\Builder $query, array $filters, array $columns): void + { + $from = trim((string) ($filters['from'] ?? '')); + $to = trim((string) ($filters['to'] ?? '')); + + if (($from === '' && $to === '') || ! isset($columns['order_time'])) { + return; + } + + $expression = $this->dateExpression($columns['order_time']); + + if ($from !== '') { + $query->whereRaw($expression . ' >= ?', [$from . ' 00:00:00']); + } + + if ($to !== '') { + $query->whereRaw($expression . ' <= ?', [$to . ' 23:59:59']); + } + } + private function dateExpression(string $column): string { // Dynamic schemas can move the source field. Keep the original parser