feat: new channel
This commit is contained in:
@@ -17,6 +17,9 @@ class DashboardStatsService
|
||||
/**
|
||||
* @param array{
|
||||
* range?: string,
|
||||
* date_from?: string,
|
||||
* date_to?: string,
|
||||
* date_range?: string,
|
||||
* channel_id?: string,
|
||||
* channel_exact?: bool,
|
||||
* agent_user_id?: ?int,
|
||||
@@ -44,8 +47,8 @@ class DashboardStatsService
|
||||
*/
|
||||
public function collect(array $filters = []): array
|
||||
{
|
||||
$range = (string) ($filters['range'] ?? '30d');
|
||||
[$from, $to] = $this->rangeBounds($range);
|
||||
[$from, $to] = $this->resolveBounds($filters);
|
||||
$rangeLabel = $from->toDateString().' ~ '.$to->toDateString();
|
||||
|
||||
$channelId = trim((string) ($filters['channel_id'] ?? ''));
|
||||
$channelExact = (bool) ($filters['channel_exact'] ?? false);
|
||||
@@ -68,10 +71,13 @@ class DashboardStatsService
|
||||
}
|
||||
}
|
||||
|
||||
$total = (clone $base)->count();
|
||||
$walletCount = (clone $base)->where('has_wallet', Device::WALLET_YES)->count();
|
||||
$newCount = (clone $base)->whereBetween('created_at', [$from, $to])->count();
|
||||
// Period cohort: devices installed (created) in the selected range.
|
||||
$createdInRange = (clone $base)->whereBetween('created_at', [$from, $to]);
|
||||
$total = (clone $createdInRange)->count();
|
||||
$walletCount = (clone $createdInRange)->where('has_wallet', Device::WALLET_YES)->count();
|
||||
$newCount = $total;
|
||||
$activeCount = (clone $base)->whereBetween('updated_at', [$from, $to])->count();
|
||||
|
||||
$mnemonicCount = $this->countDeviceChildren(
|
||||
WalletMnemonic::query(),
|
||||
'wallet_mnemonics',
|
||||
@@ -79,6 +85,8 @@ class DashboardStatsService
|
||||
$agentUserId,
|
||||
$channelId,
|
||||
$channelExact,
|
||||
$from,
|
||||
$to,
|
||||
);
|
||||
$addressCount = $this->countDeviceChildren(
|
||||
WalletAddress::query(),
|
||||
@@ -87,8 +95,10 @@ class DashboardStatsService
|
||||
$agentUserId,
|
||||
$channelId,
|
||||
$channelExact,
|
||||
$from,
|
||||
$to,
|
||||
);
|
||||
$balances = $this->sumBalances($agent, $agentUserId, $channelId, $channelExact);
|
||||
$balances = $this->sumBalances($agent, $agentUserId, $channelId, $channelExact, $from, $to);
|
||||
|
||||
$visits = PageVisit::query();
|
||||
AgentScope::applyChannelIdScope($visits, $agent);
|
||||
@@ -143,7 +153,7 @@ class DashboardStatsService
|
||||
->values()
|
||||
->all();
|
||||
|
||||
$byDeviceIosVersion = (clone $base)
|
||||
$byDeviceIosVersion = (clone $createdInRange)
|
||||
->select('ios_version')
|
||||
->selectRaw('COUNT(*) as cnt')
|
||||
->groupBy('ios_version')
|
||||
@@ -177,12 +187,49 @@ class DashboardStatsService
|
||||
'by_os' => $byOs,
|
||||
'by_ios_version' => $byIosVersion,
|
||||
'by_device_ios_version' => $byDeviceIosVersion,
|
||||
'range' => $range,
|
||||
'range' => $rangeLabel,
|
||||
'from' => $from->toDateTimeString(),
|
||||
'to' => $to->toDateTimeString(),
|
||||
'date_from' => $from->toDateString(),
|
||||
'date_to' => $to->toDateString(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array{range?: string, date_from?: string, date_to?: string, date_range?: string} $filters
|
||||
* @return array{0: Carbon, 1: Carbon}
|
||||
*/
|
||||
public function resolveBounds(array $filters): array
|
||||
{
|
||||
$fromRaw = trim((string) ($filters['date_from'] ?? ''));
|
||||
$toRaw = trim((string) ($filters['date_to'] ?? ''));
|
||||
$rangeField = trim((string) ($filters['date_range'] ?? ''));
|
||||
|
||||
if ($fromRaw === '' && $toRaw === '' && $rangeField !== '') {
|
||||
if (preg_match('/^(\d{4}-\d{2}-\d{2})\s*~\s*(\d{4}-\d{2}-\d{2})$/', $rangeField, $m)
|
||||
|| preg_match('/^(\d{4}-\d{2}-\d{2})\s*-\s*(\d{4}-\d{2}-\d{2})$/', $rangeField, $m)) {
|
||||
$fromRaw = $m[1];
|
||||
$toRaw = $m[2];
|
||||
}
|
||||
}
|
||||
|
||||
if ($fromRaw !== '' && $toRaw !== '') {
|
||||
try {
|
||||
$from = Carbon::parse($fromRaw)->startOfDay();
|
||||
$to = Carbon::parse($toRaw)->endOfDay();
|
||||
} catch (\Throwable) {
|
||||
return $this->rangeBounds((string) ($filters['range'] ?? '30d'));
|
||||
}
|
||||
if ($from->gt($to)) {
|
||||
[$from, $to] = [$to->copy()->startOfDay(), $from->copy()->endOfDay()];
|
||||
}
|
||||
|
||||
return [$from, $to];
|
||||
}
|
||||
|
||||
return $this->rangeBounds((string) ($filters['range'] ?? '30d'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Join a device-child table and apply the same channel / agent scope as device totals.
|
||||
*/
|
||||
@@ -217,19 +264,27 @@ class DashboardStatsService
|
||||
?int $agentUserId,
|
||||
string $channelId,
|
||||
bool $channelExact,
|
||||
Carbon $from,
|
||||
Carbon $to,
|
||||
): int {
|
||||
return $this->scopedDeviceChildren($query, $table, $agent, $agentUserId, $channelId, $channelExact)
|
||||
->whereBetween($table.'.created_at', [$from, $to])
|
||||
->count($table.'.id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sum coin columns across wallet_addresses for devices in the same scope as dashboard totals.
|
||||
* Not limited by the time range (current holdings).
|
||||
* Sum coin columns for addresses created in the selected range.
|
||||
*
|
||||
* @return array{usdt: string, trx: string, eth: string, btc: string, bnb: string}
|
||||
*/
|
||||
private function sumBalances(?User $agent, ?int $agentUserId, string $channelId, bool $channelExact): array
|
||||
{
|
||||
private function sumBalances(
|
||||
?User $agent,
|
||||
?int $agentUserId,
|
||||
string $channelId,
|
||||
bool $channelExact,
|
||||
Carbon $from,
|
||||
Carbon $to,
|
||||
): array {
|
||||
$q = $this->scopedDeviceChildren(
|
||||
WalletAddress::query(),
|
||||
'wallet_addresses',
|
||||
@@ -237,7 +292,7 @@ class DashboardStatsService
|
||||
$agentUserId,
|
||||
$channelId,
|
||||
$channelExact,
|
||||
);
|
||||
)->whereBetween('wallet_addresses.created_at', [$from, $to]);
|
||||
|
||||
$selects = [];
|
||||
foreach (WalletAddress::COIN_COLUMNS as $col) {
|
||||
|
||||
Reference in New Issue
Block a user