CaiWuXiTong/modules/EcommerceFinance/Services/BusinessMirrorDataReader.php

47 lines
2.1 KiB
PHP

<?php
namespace Modules\EcommerceFinance\Services;
use InvalidArgumentException;
use Modules\EcommerceFinance\Repositories\GenericBusinessMirrorRepository;
use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
/** Backend primitive: callers must retain their existing company/permission checks. */
class BusinessMirrorDataReader
{
public function __construct(
private readonly BusinessMirrorDatasetRegistry $datasets,
private readonly BusinessMirrorSchemaManager $schemas,
private readonly GenericBusinessMirrorRepository $mirror,
) {}
public function paginate(string $key, array $filters = [], int $page = 1, int $perPage = 25): array
{
$dataset = $this->datasets->get($key);
if (! $this->mirror->ready($dataset)) {
throw new ServiceUnavailableHttpException(30, '该数据集尚未完成首次同步,请查看同步状态;页面不会临时访问上游。');
}
$columns = array_column($this->schemas->columns($dataset), 'column_name');
$query = $this->mirror->connection()->table($dataset->targetTable());
foreach ($filters as $column => $value) {
if (! in_array($column, $columns, true) || (! is_scalar($value) && $value !== null)) {
throw new InvalidArgumentException('镜像筛选字段或值无效。');
}
$query->where($column, $value);
}
$total = (clone $query)->count();
foreach ($dataset->keyColumns() as $column) $query->orderBy($column);
$page = max($page, 1);
$perPage = min(max($perPage, 1), 100);
$state = $this->mirror->state($dataset);
return [
'rows' => $query->select($columns)->offset(($page - 1) * $perPage)->limit($perPage)->get()
->map(fn ($row) => (array) $row)->all(),
'total' => $total, 'page' => $page, 'per_page' => $perPage,
'last_page' => max((int) ceil($total / $perPage), 1),
'sync_status' => $state['status'] ?? 'unknown',
'last_succeeded_at' => $state['last_succeeded_at'] ?? null,
];
}
}