47 lines
2.1 KiB
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,
|
|
];
|
|
}
|
|
}
|