Files
ryobi-crawler/src/Models/Product.php
2026-02-05 08:40:34 +01:00

116 lines
2.9 KiB
PHP

<?php
namespace Krzysiej\RyobiCrawler\Models;
use Carbon\Traits\Date;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Support\Str;
use function Symfony\Component\Clock\now;
/**
* @property integer $skuID
* @property string $name
* @property integer $availableQuantity
* @property string[] $categories
* @property string $image
* @property string $subTitle
* @property string $variantCode
* @property string $modelCode
* @property string $url
* @property int $starred
* @property float $priceCurrent
* @property float $priceLowest
* @property float $productStandardPrice
* @property float $lowestProductPrice30Days
* @property Date $lastSeen
* @property integer $stock
* @property Object $promotions
*/
class Product extends Model
{
public $timestamps = true;
public $fillable = ['skuID', 'country_id'];
public function country(): BelongsTo
{
return $this->belongsTo(Country::class);
}
public function price(): HasMany
{
return $this->hasMany(Price::class);
}
public function isStarred(): bool
{
return (bool)$this->starred;
}
public function currentPrice(): HasOne
{
return $this->hasOne(Price::class)->latestOfMany('created_at');
}
public function lowestPrice(): HasOne
{
return $this->hasOne(Price::class)->ofMany('price', 'MIN');
}
public function newestPrice(): HasOne
{
return $this->hasOne(Price::class)->latest()->take(1);
}
public function stock(): HasMany
{
return $this->hasMany(Stock::class);
}
public function currentStock(): HasOne
{
return $this->stock()->one()->ofMany()->withDefault(fn(Stock $stock) => $stock->stock = 0)->take(1);
}
public function toggleStarred(): self
{
$this->starred = !$this->starred;
return $this;
}
public function categories(): Attribute
{
return Attribute::make(
get: fn(string $value) => array_reverse(json_decode($value, 1)),
set: fn(array $value) => json_encode($value),
);
}
public function promotions(): Attribute
{
return Attribute::make(
get: fn(?string $value) => json_decode($value ?? '{"hasPromotion": false}', 1),
set: function (\stdClass $value) {
$value->slug = Str::slug($value->tag);
return json_encode($value);
}
);
}
public function isDiscontinued(): bool
{
return $this->lastSeen < now()->format('Y-m-d');
}
public function isNew(): bool
{
return $this->created_at->format('Y-m-d') > now()->modify('-30 days')->format('Y-m-d');
}
}