File "Product.php"

Full Path: /home/clickysoft/public_html/jmapi5.clickysoft.net/app/Models/Product.php
File size: 8.86 KB
MIME-type: text/x-php
Charset: utf-8

<?php

namespace App\Models;

use App\Http\Controllers\Traits\MediaUploadingTrait;
use \DateTimeInterface;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
use Spatie\Sluggable\HasSlug;
use Spatie\Sluggable\SlugOptions;

class Product extends Model implements HasMedia
{
    use InteractsWithMedia, MediaUploadingTrait;
    use HasFactory, HasSlug;

    public const STATUS_RADIO = [
        '1' => 'Enable',
        '0' => 'Disable',
    ];

    public const DRAFT_RADIO = [
        '1' => 'Yes',
        '0' => 'No',
    ];

    public const PRODUCT_TYPE = [
        'standard' => 'Standard',
        'configurable' => 'Configurable',
    ];

    public $table = 'products';

    protected $dates = [
        'created_at',
        'updated_at',
        'deleted_at',
    ];

    protected $casts = [
        'created_at' => 'date:m-d-Y',
        'updated_at' => 'date:m-d-Y',
    ];

    protected $appends = [
        'featured_image',
        'gallery_images',
        'product_sketch',
    ];

    protected $fillable = [
        'vendor_id',
        'sku',
        'name',
        'slug',
        'description',
        'engraving',
        'color_engraving',
        'engraving_fee',
        'price_from',
        'price_to',
        'product_sketch',
        'status',
        'created_at',
        'updated_at',
        'deleted_at',
        'category_id',
        'has_variations',
        'product_type',
        'is_draft',
    ];

    public function getSlugOptions() : SlugOptions
    {
        return SlugOptions::create()
            ->generateSlugsFrom('name')
            ->saveSlugsTo('slug')
            ->slugsShouldBeNoLongerThan(100);
    }

    public function registerMediaConversions(Media $media = null): void
    {
        $this->addMediaConversion('thumb')->fit('crop', 50, 50)->nonQueued();
        $this->addMediaConversion('preview')->fit('crop', 120, 120)->nonQueued();
    }

    public function productProductPrices()
    {
        return $this->hasMany(ProductPrice::class, 'product_id', 'id');
    }

    public function reviews()
    {
        return $this->hasMany(Review::class, 'product_id');
    }

    public function category()
    {
        return $this->belongsTo(Category::class, 'category_id');
    }

    public function vendor()
    {
        return $this->belongsTo(Vendor::class, 'vendor_id');
    }

    public function getFeaturedImageAttribute()
    {
        $file = $this->getMedia('product_featured_image')->last();
        if ($file) {
            $file->url       = $file->getUrl();
            $file->thumbnail = $file->getUrl('thumb');
            $file->preview   = $file->getUrl('preview');
        }

        return $file;
    }

    protected function getStatusNameAttribute()
    {
        return self::STATUS_RADIO[$this->status];
    }

    protected function getProductSketchMediaAttribute()
    {
        return $this->product_sketch
            ? asset('storage/product/'.$this->product_sketch)
            : "";
    }

    public function getGalleryImagesAttribute()
    {
        $files = $this->getMedia('gallery_image');
        $files->each(function ($item) {
            $item->url = $item->getUrl();
            $item->thumbnail = $item->getUrl('thumb');
            $item->preview = $item->getUrl('preview');
        });

        return $files;
    }

    protected function serializeDate(DateTimeInterface $date)
    {
        return $date->format('Y-m-d H:i:s');
    }

    public function scopeActive($query)
    {
        return $query->where('status', 1);
    }

    public function scopePublished($query)
    {
        return $query->where('is_draft', 0);
    }

    public function variations()
    {
        return $this->hasMany(ProductVariation::class, 'product_id');
    }

    public function prices()
    {
        return $this->hasMany(ProductPrice::class);
    }

    public function handleVariations($request)
    {
        foreach ($request['variations'] as $variation){
            $v = ProductVariation::updateOrCreate([
                'product_id' => $this->id,
                'variation_id' => $variation,
            ],[
                'product_id' => $this->id,
                'variation_id' => $variation,
            ]);

            $v_ids[] = $v->id;
        }

        $product_min_price = 0;
        $product_max_price = 0;
        $product_price_ids = [];

        foreach ($request['combinations'] as $combination){
            $product_price = ProductPrice::where('supplier_prod_number', $combination['supplier_prod_number'])->first();

            if ($product_price) {
                $product_price->product_id = $this->id;
                $product_price->vendor_price = $combination['vendor_price'] ?? null;
                $product_price->shipping_weight = $combination['shipping_weight'];
                $product_price->length = $combination['length'];
                $product_price->width = $combination['width'];
                $product_price->height = $combination['height'];
                $product_price->save();
            } else {
                $product_price = ProductPrice::create([
                    'product_id' => $this->id,
                    'vendor_price' => $combination['vendor_price'] ?? null,
                    'supplier_prod_number' => $combination['supplier_prod_number'],
                    'shipping_weight' => $combination['shipping_weight'],
                    'length' => $combination['length'],
                    'width' => $combination['width'],
                    'height' => $combination['height'],
                ]);
            }

            $product_price_ids[] = $product_price->id;

            if (isset($combination['product_sketch']) && is_file($combination['product_sketch'])) {
                $product_price->product_sketch = $this->storePDF($combination['product_sketch'], $product_price->id, 'variation');
                $product_price->save();
            }

            $product_variation_combination = [];
            $price_ranges = [];

            foreach ($combination['variations'] as $v){

                $product_variation_combination[] = [
                    'product_id' => $this->id,
                    'variation_id' => $v,
                    'product_price_id' => $product_price->id,
                    'created_at' => now(),
                    'updated_at' => now(),
                ];
            }

            $min_price = 0;
            $max_price = 0;

            foreach ($combination['price_ranges'] as $range){
                $price_ranges[] = [
                    'product_id' => $this->id,
                    'product_price_id' => $product_price->id,
                    'qty_from' => $range['qty_from'],
                    'qty_to' => $range['qty_to'],
                    'price' => $range['price'],
                    'created_at' => now(),
                    'updated_at' => now(),
                ];

                $min_price = $min_price == 0
                    ? $range['price']
                    : min($range['price'], $min_price);

                $max_price = $max_price == 0
                    ? $range['price']
                    : max($range['price'], $max_price);

                $product_min_price = $product_min_price == 0
                    ? $min_price :
                    min($product_min_price, $min_price);

                $product_max_price = $product_max_price == 0
                    ? $max_price :
                    max($product_max_price, $max_price);
            }

            ProductVariationCombination::where('product_price_id',$product_price->id)->delete();
            ProductVariationCombination::insert($product_variation_combination);

            ProductVariationRange::where('product_price_id',$product_price->id)->delete();
            ProductVariationRange::insert($price_ranges);

            $product_price->min_price = $min_price;
            $product_price->max_price = $max_price;
            $product_price->avg_price = ($min_price + $max_price) / 2;
            $product_price->save();
        }

        //Delete combinations that are not in array while updating product
        ProductVariationCombination::whereNotIn('product_price_id',$product_price_ids)
            ->where('product_id', $this->id)->delete();

        ProductVariationRange::whereNotIn('product_price_id',$product_price_ids)
            ->where('product_id', $this->id)->delete();

        //To delete the price id that is not included in request array
        ProductPrice::whereNotIn('id', $product_price_ids)
            ->where('product_id', $this->id)->delete();

        $this->variations()->whereNotIn('id', $v_ids)->delete();
        $this->price_from = $product_min_price;
        $this->price_to = $product_max_price;
        $this->avg_price = ($product_min_price + $product_max_price) / 2;
        $this->save();
    }
}