120 lines
4.3 KiB
PHP
120 lines
4.3 KiB
PHP
<?php
|
||
|
||
namespace Modules\EcommerceFinance\Repositories;
|
||
|
||
use Modules\EcommerceFinance\Services\BusinessMirrorDatasetRegistry;
|
||
use RuntimeException;
|
||
|
||
class StoreAccountMirrorRepository
|
||
{
|
||
public const DATASET = 'database_4.external_store_accounts.accounts_v1';
|
||
|
||
public function __construct(
|
||
private readonly BusinessMirrorDatasetRegistry $datasets,
|
||
private readonly GenericBusinessMirrorRepository $mirror,
|
||
) {}
|
||
|
||
/** @return array{data:array<int,array<string,mixed>>,total:int} */
|
||
public function paginate(int $page, int $perPage): array
|
||
{
|
||
$dataset = $this->datasets->get(self::DATASET);
|
||
if (! $this->mirror->ready($dataset)) {
|
||
throw new RuntimeException('store_account_mirror_not_ready');
|
||
}
|
||
|
||
$page = max($page, 1);
|
||
$perPage = min(max($perPage, 1), 100);
|
||
$query = $this->mirror->connection()->table($dataset->targetTable());
|
||
$total = (clone $query)->count();
|
||
$rows = $query
|
||
->orderByDesc('id')
|
||
->forPage($page, $perPage)
|
||
->get()
|
||
->map(fn (object $row): array => [
|
||
'id' => $row->id,
|
||
'store_name' => $row->storeName,
|
||
'operation_owner' => $row->operationOwner,
|
||
'operation_department_head' => $row->operationDepartmentHead,
|
||
'operation_director' => $row->operationDirector,
|
||
'profit_center' => $row->profitCenter,
|
||
'account_type' => $this->accountType($row->accountType),
|
||
'account' => $row->account,
|
||
// Only the safe boolean may enter the mirror, never a password.
|
||
'password_configured' => isset($row->passwordConfigured) ? (bool) $row->passwordConfigured : null,
|
||
'bound_phone' => $row->boundPhone,
|
||
'verification_contact' => $row->verificationContact,
|
||
'account_group_name' => $row->accountGroupName,
|
||
'created_at' => $row->createdAt,
|
||
'updated_at' => $row->updatedAt,
|
||
])
|
||
->all();
|
||
|
||
return ['data' => $rows, 'total' => $total];
|
||
}
|
||
|
||
public function containsAccount(string $id): bool
|
||
{
|
||
$dataset = $this->datasets->get(self::DATASET);
|
||
if (! $this->mirror->ready($dataset)) {
|
||
throw new RuntimeException('store_account_mirror_not_ready');
|
||
}
|
||
return $this->mirror->connection()->table($dataset->targetTable())->where('id', $id)->exists();
|
||
}
|
||
|
||
public function containsAccounts(array $ids): bool
|
||
{
|
||
$ids = array_values(array_unique($ids));
|
||
if ($ids === []) {
|
||
return false;
|
||
}
|
||
$dataset = $this->datasets->get(self::DATASET);
|
||
if (! $this->mirror->ready($dataset)) {
|
||
throw new RuntimeException('store_account_mirror_not_ready');
|
||
}
|
||
return $this->mirror->connection()->table($dataset->targetTable())
|
||
->whereIn('id', $ids)->distinct()->count('id') === count($ids);
|
||
}
|
||
|
||
/**
|
||
* 店铺维度报表的归属字段覆盖表,以店铺名称(storeName)为键。
|
||
*
|
||
* @return array<string,array{operation_owner:string,operation_director:string,profit_center:string}>
|
||
*/
|
||
public function ownershipByStoreName(): array
|
||
{
|
||
$dataset = $this->datasets->get(self::DATASET);
|
||
if (! $this->mirror->ready($dataset)) {
|
||
throw new RuntimeException('store_account_mirror_not_ready');
|
||
}
|
||
|
||
$map = [];
|
||
foreach ($this->mirror->connection()->table($dataset->targetTable())
|
||
->select('storeName', 'operationOwner', 'operationDirector', 'profitCenter')
|
||
->get() as $row) {
|
||
$name = trim((string) $row->storeName);
|
||
if ($name === '') {
|
||
continue;
|
||
}
|
||
$map[$name] = [
|
||
'operation_owner' => trim((string) $row->operationOwner),
|
||
'operation_director' => trim((string) $row->operationDirector),
|
||
'profit_center' => trim((string) $row->profitCenter),
|
||
];
|
||
}
|
||
|
||
return $map;
|
||
}
|
||
|
||
private function accountType(mixed $value): ?string
|
||
{
|
||
$type = trim((string) $value);
|
||
|
||
return match (strtoupper($type)) {
|
||
'MAIN' => '主账号',
|
||
'SUB' => '子账号',
|
||
'', '/' => null,
|
||
default => $type,
|
||
};
|
||
}
|
||
}
|