CaiWuXiTong/modules/EcommerceFinance/View/CostFreightAnomalyPageData.php
renshen 1b6ff0bb75 feat: 新增成本运费异常监控 (#992)
成本/运费异常页监控商品成本和快递费同时缺失的订单。
2026-11-07 18:04:44 +08:00

117 lines
3.9 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace Modules\EcommerceFinance\View;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Collection;
use Modules\EcommerceFinance\Repositories\CostFreightAnomalyRepository;
class CostFreightAnomalyPageData
{
public function __construct(private readonly CostFreightAnomalyRepository $repository)
{
}
public function page(): array
{
return ['view' => 'business.pages.fee-ratio-monitoring.cost-freight-anomaly'] + $this->data();
}
public function data(?array $input = null, ?int $page = null, ?int $limit = null): array
{
$filters = $this->filters($input);
$page = max($page ?? (int) request('page', 1), 1);
$limit = min(max($limit ?? (int) setting('default.list_limit', 25), 1), 100);
$status = $this->repository->status();
$rows = new Paginator([], $limit, $page, [
'path' => request()->url(),
'query' => request()->except('page'),
]);
$error = null;
if (! $status['ready']) {
$error = '成本/运费异常共享镜像尚未就绪。';
} else {
try {
$result = $this->repository->paginate($filters, $page, $limit);
$rows = new Paginator(
Collection::make($result['rows'])
->map(static fn (array $row): object => (object) $row),
$limit,
$page,
[
'path' => request()->url(),
'query' => request()->except('page'),
],
);
$rows->hasMorePagesWhen((bool) $result['has_more']);
$status['total'] = $result['total'];
} catch (\Throwable $exception) {
report($exception);
$error = '成本/运费异常数据暂时无法读取,请稍后重试。';
}
}
return [
'costFreightRows' => $rows,
'costFreightFilters' => $filters,
'costFreightStatus' => $status,
'costFreightShopOptions' => $status['shops'] ?? [],
'costFreightError' => $error,
];
}
/** @return array{from:string,to:string,order_no:string,shop_names:array<int,string>} */
private function filters(?array $input): array
{
$input ??= request()->query();
$shops = [];
foreach ((array) ($input['shop_name'] ?? $input['shop_names'] ?? []) as $shop) {
$shop = trim((string) $shop);
if ($shop !== '') {
$shops[$shop] = true;
}
}
$datesSubmitted = array_key_exists('from', $input) || array_key_exists('to', $input);
$from = $this->date($input['from'] ?? null);
$to = $this->date($input['to'] ?? null);
if (! $datesSubmitted && empty($input['reset'])) {
$from = now()->subDays(6)->toDateString();
$to = now()->toDateString();
}
return [
'from' => $from,
'to' => $to,
'order_no' => $this->batchText($input['order_no'] ?? null),
'shop_names' => array_keys($shops),
];
}
private function date(mixed $value): string
{
$value = trim((string) $value);
$timestamp = $value === '' ? false : strtotime($value);
return $timestamp === false ? '' : date('Y-m-d', $timestamp);
}
private function batchText(mixed $value): string
{
$values = is_array($value) ? $value : preg_split('/[\r\n,,;;]+/u', (string) $value);
$items = [];
foreach ((array) $values as $item) {
$item = trim((string) $item);
if ($item !== '') {
$items[$item] = true;
}
if (count($items) >= 100) {
break;
}
}
return implode("\n", array_keys($items));
}
}