Files
portal-api/app/Models/Product.php
T

166 lines
4.2 KiB
PHP

<?php
namespace App\Models;
use App\Traits\HasUuid;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Product extends Model
{
use HasFactory, HasUuid, SoftDeletes;
protected array $uuidColumns = ['uuid'];
protected string $slugColumn = 'name';
protected $fillable = [
'name',
'slug',
'short_description',
'description',
'thumbnail',
'gallery',
'setup_fee',
'trial_days',
'cpu',
'ram',
'gpu',
'disk',
'bandwidth',
'stock',
'is_unlimited',
'is_active',
'sort_order',
'product_categories_id',
'published_at',
];
protected $casts = [
'is_active' => 'boolean',
'is_unlimited' => 'boolean',
'published_at' => 'date',
'gallery' => 'array',
'product_type' => 'string',
];
protected static function boot()
{
parent::boot();
static::saving(function ($product) {
if ($product->product_categories_id) {
$category = ProductCategories::find($product->product_categories_id);
if ($category && $category->type) {
$product->product_type = $category->type;
}
}
});
}
/**
* Relationship: Product belongs to a Category
*/
public function category()
{
return $this->belongsTo(ProductCategories::class, 'product_categories_id');
}
/**
* Relationship: Product has many OS versions (pivot table: os_product)
*/
public function osVersions()
{
return $this->belongsToMany(Os::class, 'os_product', 'product_id', 'os_id')
->withTimestamps();
}
/**
* Relationship: Product has many OS via product_os table (VPS OS selection)
*/
public function operatingSystems()
{
return $this->belongsToMany(Os::class, 'os_product', 'product_id', 'os_id')
->withTimestamps();
}
/**
* Relationship: Product has many Control Panels (for Hosting)
*/
public function controlPanels()
{
return $this->belongsToMany(ControlPanel::class, 'product_control_panel')
->withPivot(['price_modifier', 'is_default'])
->withTimestamps();
}
/**
* Relationship: Product has many pricings
*/
public function pricings()
{
return $this->hasMany(ProductPricings::class, 'product_id');
}
/**
* Relationship: Product has many order items
*/
public function orderItems()
{
return $this->hasMany(OrderItem::class, 'product_id');
}
/**
* Relationship: Product has many orders through order items
*/
public function orders()
{
return $this->hasManyThrough(Order::class, OrderItem::class, 'product_id', 'id', 'id', 'order_id');
}
/**
* Legacy: Many-to-many categories (if still needed)
*/
public function categories()
{
return $this->belongsToMany(ProductCategories::class, 'product_product_category', 'product_id', 'product_category_id');
}
/**
* Relationship: Product has many addons (through product type)
* Addons are linked via type in product_addon table
*/
public function addons()
{
return $this->hasMany(Addon::class, 'type', 'product_type')
->orderBy('sort_order');
}
/**
* Get monthly pricing (or first available pricing)
*/
public function getMonthlyPricingAttribute()
{
return $this->pricings()
->where('is_active', 1)
->where('billing_cycle', 'monthly')
->first()
?? $this->pricings()->where('is_active', 1)->orderBy('price')->first();
}
/**
* Get display price (sale price if available, otherwise regular price)
*/
public function getPriceAttribute()
{
$pricing = $this->monthlyPricing;
return $pricing ? $pricing->price : 0;
}
public function getPriceSaleAttribute()
{
$pricing = $this->monthlyPricing;
return $pricing ? $pricing->price_sale : null;
}
}