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/AdProductCatalog.php
<?php

namespace App\Model;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use App\Library\Traits\HasUid;

/**
 * @property int $id
 * @property string $uid
 * @property int $customer_id
 * @property int|null $ad_platform_id
 * @property string $name
 * @property string $source_type
 * @property string|null $source_url
 * @property string $sync_status
 * @property \Illuminate\Support\Carbon|null $last_synced_at
 * @property int $product_count
 * @property string|null $platform_catalog_id
 * @property string|null $last_idempotency_key
 * @property array<int,array<string,string>>|null $error_log
 */
class AdProductCatalog extends Model
{
    use HasFactory;
    use HasUid;

    const STATUS_ACTIVE = 'active'; // for HasUid trait compatibility

    const SOURCE_MANUAL = 'manual';
    const SOURCE_FEED_URL = 'feed_url';
    const SOURCE_SHOPIFY = 'shopify';
    const SOURCE_WOOCOMMERCE = 'woocommerce';
    // R15.6 — CSV upload (admin uploads a file from disk OR points
    // source_url at a CSV-serving HTTPS URL).
    const SOURCE_CSV = 'csv';

    const SOURCES = [
        self::SOURCE_MANUAL,
        self::SOURCE_FEED_URL,
        self::SOURCE_SHOPIFY,
        self::SOURCE_WOOCOMMERCE,
        self::SOURCE_CSV,
    ];

    const SYNC_PENDING = 'pending';
    const SYNC_IN_PROGRESS = 'in_progress';
    const SYNC_COMPLETED = 'completed';
    const SYNC_FAILED = 'failed';
    const SYNC_PARTIAL = 'partial';

    protected $table = 'ad_product_catalogs';

    protected $fillable = [
        'uid',
        'customer_id',
        'ad_platform_id',
        'name',
        'source_type',
        'source_url',
        'source_credentials',
        'sync_status',
        'last_synced_at',
        'last_source_pulled_at',
        'product_count',
        'platform_catalog_id',
        'last_idempotency_key',
        'error_log',
    ];

    protected $casts = [
        'last_synced_at' => 'datetime',
        'last_source_pulled_at' => 'datetime',
        'error_log' => 'json',
        // R15.5 — encrypted JSON for WooCommerce / Shopify / feed-URL
        // creds.  Never plaintext at rest.
        'source_credentials' => 'encrypted:json',
    ];

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

    /**
     * @return BelongsTo<AdPlatform, $this>
     */
    public function adPlatform(): BelongsTo
    {
        return $this->belongsTo(AdPlatform::class, 'ad_platform_id');
    }

    /**
     * @return HasMany<AdProduct, $this>
     */
    public function products(): HasMany
    {
        return $this->hasMany(AdProduct::class, 'ad_product_catalog_id');
    }

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

    public function scopeSearch($query, $keyword)
    {
        return $keyword ? $query->where('name', 'like', '%' . $keyword . '%') : $query;
    }

    public function getSyncBadgeAttribute(): string
    {
        return match ($this->sync_status) {
            self::SYNC_COMPLETED => 'green',
            self::SYNC_IN_PROGRESS => 'blue',
            self::SYNC_FAILED => 'red',
            default => 'orange',
        };
    }

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