HEX
Server: LiteSpeed
System: Linux s1049.use1.mysecurecloudhost.com 4.18.0-477.27.2.lve.el8.x86_64 #1 SMP Wed Oct 11 12:32:56 UTC 2023 x86_64
User: xedaptot (3356)
PHP: 8.3.31
Disabled: NONE
Upload Files
File: /home/xedaptot/be.naniguide.com/app/Model/AdAudience.php
<?php

namespace App\Model;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Library\Traits\HasUid;

class AdAudience extends Model
{
    use HasFactory;
    use HasUid;
    use SoftDeletes;

    // Types
    const TYPE_CUSTOM = 'custom';
    const TYPE_LOOKALIKE = 'lookalike';
    const TYPE_SAVED = 'saved';

    const TYPES = [
        self::TYPE_CUSTOM,
        self::TYPE_LOOKALIKE,
        self::TYPE_SAVED,
    ];

    const TYPE_LABELS = [
        self::TYPE_CUSTOM => 'Custom Audience',
        self::TYPE_LOOKALIKE => 'Lookalike Audience',
        self::TYPE_SAVED => 'Saved Audience',
    ];

    // Source types
    const SOURCE_MAIL_LIST = 'mail_list';
    const SOURCE_SEGMENT = 'segment';
    const SOURCE_MANUAL = 'manual';

    // Statuses
    const STATUS_DRAFT = 'draft';
    const STATUS_SYNCING = 'syncing';
    const STATUS_SYNCED = 'synced';
    const STATUS_ERROR = 'error';
    const STATUS_STALE = 'stale';
    const STATUS_ACTIVE = 'synced'; // alias for HasUid trait compatibility

    const STATUSES = [
        self::STATUS_DRAFT,
        self::STATUS_SYNCING,
        self::STATUS_SYNCED,
        self::STATUS_ERROR,
        self::STATUS_STALE,
    ];

    const STATUS_BADGE_MAP = [
        self::STATUS_DRAFT => 'orange',
        self::STATUS_SYNCING => 'blue',
        self::STATUS_SYNCED => 'green',
        self::STATUS_ERROR => 'red',
        self::STATUS_STALE => 'orange',
    ];

    // Sync statuses
    const SYNC_PENDING = 'pending';
    const SYNC_IN_PROGRESS = 'in_progress';
    const SYNC_COMPLETED = 'completed';
    const SYNC_FAILED = 'failed';

    protected $table = 'ad_audiences';

    protected $fillable = [
        'uid',
        'customer_id',
        'name',
        'type',
        'source_type',
        'source_id',
        'platform',
        'platform_audience_id',
        'size_estimate',
        'status',
        'sync_status',
        'last_synced_at',
        'settings',
        'sync_error',
    ];

    protected $casts = [
        'settings' => 'json',
        'last_synced_at' => 'datetime',
        'size_estimate' => 'integer',
    ];

    // ── Relations ──────────────────────────────────────────────────────────

    public function customer()
    {
        return $this->belongsTo(Customer::class, 'customer_id');
    }

    public function mailList()
    {
        return $this->belongsTo(MailList::class, 'source_id');
    }

    public function activityLogs()
    {
        return $this->morphMany(AdActivityLog::class, 'loggable');
    }

    // ── Scopes ─────────────────────────────────────────────────────────────

    public function scopeOfCustomer($query, $customerId)
    {
        return $query->where('customer_id', $customerId);
    }

    public function scopeSearch($query, $keyword)
    {
        if (!$keyword) {
            return $query;
        }

        return $query->where('name', 'like', '%' . $keyword . '%');
    }

    public function scopeOfType($query, $type)
    {
        if (!$type) {
            return $query;
        }

        return $query->where('type', $type);
    }

    public function scopeOfPlatform($query, $platform)
    {
        if (!$platform) {
            return $query;
        }

        return $query->where('platform', $platform);
    }

    public function scopeSynced($query)
    {
        return $query->where('status', self::STATUS_SYNCED);
    }

    // ── Accessors ──────────────────────────────────────────────────────────

    public function getTypeLabelAttribute(): string
    {
        return self::TYPE_LABELS[$this->type] ?? ucfirst($this->type);
    }

    public function getStatusBadgeAttribute(): string
    {
        return self::STATUS_BADGE_MAP[$this->status] ?? 'blue';
    }

    public function getSizeDisplayAttribute(): string
    {
        if (!$this->size_estimate) {
            return '-';
        }

        if ($this->size_estimate >= 1000000) {
            return round($this->size_estimate / 1000000, 1) . 'M';
        }
        if ($this->size_estimate >= 1000) {
            return round($this->size_estimate / 1000, 1) . 'K';
        }

        return number_format($this->size_estimate);
    }

    public function getSourceNameAttribute(): string
    {
        if ($this->source_type === self::SOURCE_MAIL_LIST && $this->source_id) {
            $list = MailList::find($this->source_id);
            return $list ? $list->name : 'Deleted List';
        }

        return ucfirst($this->source_type ?? 'manual');
    }

    // ── Helpers ─────────────────────────────────────────────────────────────

    public function isSynced(): bool
    {
        return $this->status === self::STATUS_SYNCED;
    }

    public function isSyncing(): bool
    {
        return $this->status === self::STATUS_SYNCING;
    }

    public function hasError(): bool
    {
        return $this->status === self::STATUS_ERROR;
    }

    // ── Factory ─────────────────────────────────────────────────────────────

    protected static function newFactory()
    {
        return \Database\Factories\AdAudienceFactory::new();
    }
}