fix notif 3
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Customer;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* مخاطب اعلان داخل اپ — همسبک سگمنتهای پیامک + غیرفعالهای اخیر.
|
||||
*/
|
||||
class AppNotificationAudienceService
|
||||
{
|
||||
public const TYPE_ALL = 'all';
|
||||
|
||||
public const TYPE_SEGMENT = 'segment';
|
||||
|
||||
public const TYPE_CUSTOMERS = 'customers';
|
||||
|
||||
/** @return array<int, array{key: string, name: string, description: string}> */
|
||||
public function segmentOptions(): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
'key' => 'all_household',
|
||||
'name' => 'همه کاربران خانگی',
|
||||
'description' => 'همه مشتریان نوع خانگی (آرشیو نشده)',
|
||||
],
|
||||
[
|
||||
'key' => 'no_login',
|
||||
'name' => 'هرگز وارد اپ نشدهاند',
|
||||
'description' => 'آخرین بازدید خالی است',
|
||||
],
|
||||
[
|
||||
'key' => 'inactive_7d',
|
||||
'name' => '۷ روز اخیر نیامدهاند',
|
||||
'description' => 'آخرین بازدید بیش از ۷ روز پیش یا هرگز',
|
||||
],
|
||||
[
|
||||
'key' => 'inactive_30d',
|
||||
'name' => '۳۰ روز اخیر نیامدهاند',
|
||||
'description' => 'آخرین بازدید بیش از ۳۰ روز پیش یا هرگز',
|
||||
],
|
||||
[
|
||||
'key' => 'no_valid',
|
||||
'name' => 'احراز هویت نشده',
|
||||
'description' => 'is_legal = 0',
|
||||
],
|
||||
[
|
||||
'key' => 'active_wallet',
|
||||
'name' => 'کاربران فعال (دارای کیف)',
|
||||
'description' => 'حداقل یک ردیف در wallets دارند',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function segmentLabel(string $key): string
|
||||
{
|
||||
foreach ($this->segmentOptions() as $opt) {
|
||||
if ($opt['key'] === $key) {
|
||||
return $opt['name'];
|
||||
}
|
||||
}
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, string> $segmentKeys
|
||||
* @return Collection<int, array{id: int, name: ?string, mobile: ?string}>
|
||||
*/
|
||||
public function resolveSegmentCustomers(array $segmentKeys): Collection
|
||||
{
|
||||
$byId = [];
|
||||
foreach ($segmentKeys as $key) {
|
||||
foreach ($this->customersForSegment((string) $key) as $row) {
|
||||
$id = (int) ($row['id'] ?? 0);
|
||||
if ($id > 0) {
|
||||
$byId[$id] = $row;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return collect(array_values($byId));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, int> $customerIds
|
||||
* @return Collection<int, array{id: int, name: ?string, mobile: ?string}>
|
||||
*/
|
||||
public function resolveCustomersByIds(array $customerIds): Collection
|
||||
{
|
||||
$ids = array_values(array_unique(array_filter(array_map('intval', $customerIds))));
|
||||
if ($ids === []) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
return Customer::query()
|
||||
->whereIn('id', $ids)
|
||||
->where('is_archive', false)
|
||||
->get(['id', 'name', 'mobile'])
|
||||
->map(fn (Customer $c) => [
|
||||
'id' => (int) $c->id,
|
||||
'name' => $c->name,
|
||||
'mobile' => $c->mobile,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, string> $segmentKeys
|
||||
*/
|
||||
public function buildAudienceLabel(string $audienceType, array $segmentKeys = [], int $recipientsCount = 0): string
|
||||
{
|
||||
return match ($audienceType) {
|
||||
self::TYPE_ALL => 'همه کاربران',
|
||||
self::TYPE_SEGMENT => collect($segmentKeys)
|
||||
->map(fn ($k) => $this->segmentLabel((string) $k))
|
||||
->filter()
|
||||
->implode(' + ') ?: 'گروهی',
|
||||
self::TYPE_CUSTOMERS => $recipientsCount <= 1
|
||||
? 'تکی'
|
||||
: ('تکی / چندنفره (' . $recipientsCount . ' نفر)'),
|
||||
default => $audienceType,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, array{id: int, name: ?string, mobile: ?string}>
|
||||
*/
|
||||
private function customersForSegment(string $key): array
|
||||
{
|
||||
$base = Customer::query()
|
||||
->where('type', 2)
|
||||
->where('is_archive', false);
|
||||
|
||||
$query = match ($key) {
|
||||
'all_household' => $base,
|
||||
'no_login' => (clone $base)->whereNull('last_seen_at'),
|
||||
'inactive_7d' => (clone $base)->where(function ($q) {
|
||||
$q->whereNull('last_seen_at')
|
||||
->orWhere('last_seen_at', '<', now()->subDays(7));
|
||||
}),
|
||||
'inactive_30d' => (clone $base)->where(function ($q) {
|
||||
$q->whereNull('last_seen_at')
|
||||
->orWhere('last_seen_at', '<', now()->subDays(30));
|
||||
}),
|
||||
'no_valid' => (clone $base)->where('is_legal', 0),
|
||||
'active_wallet' => (clone $base)->whereIn('id', function ($q) {
|
||||
$q->select('owner')->from('wallets');
|
||||
}),
|
||||
default => null,
|
||||
};
|
||||
|
||||
if ($query === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $query->get(['id', 'name', 'mobile'])->map(fn (Customer $c) => [
|
||||
'id' => (int) $c->id,
|
||||
'name' => $c->name,
|
||||
'mobile' => $c->mobile,
|
||||
])->all();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user