商品利润镜像:单号查询改走索引,修复页面 504 #471
@ -86,7 +86,33 @@ class GoodsProfitAfsRepository
|
||||
/** @param array<string,mixed> $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<string,mixed> $filters
|
||||
* @param array<string,string> $columns
|
||||
* @param list<string> $select
|
||||
* @return array{rows:list<array<string,mixed>>,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<string,mixed> $filters
|
||||
* @param array<string,string> $columns
|
||||
@ -189,6 +289,30 @@ class GoodsProfitAfsRepository
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string,mixed> $filters
|
||||
* @param array<string,string> $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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user