Files
getgreen-backend/app/Models/Product.php
2026-04-28 15:02:06 +05:00

549 lines
15 KiB
PHP
Executable File

<?php
namespace App\Models;
use App\Traits\LogOptionsTrait;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Support\Facades\App;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Facades\Storage;
use Spatie\Activitylog\Traits\LogsActivity;
/**
* Class Product
*
* @property string|null $name
* @property string|null $body
* @property string|null $short_body
* @property string|null $slug
* @property array|null $colors
* @property array|null $sizes
* @property integer|null $price
* @property boolean|null $published
* @property integer|null $price_discount
* @property integer|null $child_id
* @property string|null $poster
* @property string|null $poster_thumb
* @property boolean|null $popular
* @property boolean|null $leader_of_sales
* @property integer $article_number
* @property float $price_credit
* @property string $currency
* @property integer $brand_id
* @property integer $color_id
* @property integer $count
* @property integer $measurement_id
* @property array|null $keywords
* @property array|null $descriptions
* @property array|null $title_seo
* @property boolean $available
* @property string $data_sheet
* @property boolean $is_ready_solution
*
* @property-read Category $category
* @property-read Brand $brand
* @property-read Color $color
* @property-read Collection|Product[] $childrens
* @property-read Collection|Product|BelongsTo $product
* @property-read Collection|Product[] $childrensColor
* @property-read Collection|Compilation[] $compilations
* @property-read Collection|Comment[] $comments
* @property-read Collection|Characteristic[] $characteristics
* @property-read Collection|Basket[] $baskets
* @property-read Collection|Screen[] $screens
* @property-read Collection|Category[] $categories
*
* @property-read bool $is_favorite
* @property-read bool $is_cart
* @property-read bool $is_available
* @property float $final_price
* @property bool $diff_date
* @property bool $in_cart
*
* @method getName(): string
* @method getTitleSeo(): string
* @method getBody(): string
* @method getShortBody(): string
* @method getKeywords(): string
* @method getPrice(): float
* @method getPoster(): string
*/
class Product extends Model
{
use SoftDeletes, LogsActivity, LogOptionsTrait;
protected $appends = ['isFavorite', 'diffDate', 'isCart', 'onCredit', 'isAvailable', 'finalPrice'];
protected $guarded = ['id'];
protected $casts = [
'name' => 'array',
'body' => 'array',
'short_body' => 'array',
'slug' => 'string',
'sizes' => 'array',
'poster' => 'string',
'poster_thumb' => 'string',
'price' => 'float',
'price_discount' => 'float',
'price_credit' => 'float',
'currency' => 'string',
'article_number' => 'string',
'published' => 'boolean',
'popular' => 'boolean',
'leader_of_sales' => 'boolean',
//'category_id' => 'array',
'brand_id' => 'integer',
'color_id' => 'integer',
'child_id' => 'integer',
'available' => 'boolean',
'count' => 'integer',
'keywords' => 'array',
'descriptions' => 'array',
'title_seo' => 'array',
'is_ready_solution' => 'boolean'
];
protected $hidden = [
'child_id',
'deleted_at'
];
protected static $logName = 'products';
protected static $logOnlyDirty = true;
protected static $logAttributes = ['name', 'price', 'price_discount', 'article_number', 'published', 'available', 'count', 'title_seo', 'price_credit'];
protected static $submitEmptyLogs = false;
public function getFinalPriceAttribute()
{
if (!empty($this->price_discount)) {
return $this->price_discount;
} else {
return $this->price;
}
}
public function getInCartAttribute()
{
$user = getAuthUser();
$userId = $user?->id;
$token = request()->header('X-Application-Token');
$cartQuery = Cart::where('product_id', $this->id);
if (isset($userId)) {
$cartQuery->where('user_id', $userId);
$cart = $cartQuery->first();
if ($cart) {
return $cart->count;
}
}
if (isset($token)) {
$cartQuery->where('token', $token);
$cart = $cartQuery->first();
if ($cart) {
return $cart->count;
}
}
return 0;
}
public function getName(): string
{
if (App::isLocale('ru')) {
return (string) $this->name['ru'];
}
return (string) $this->name['uz'];
}
public function getTitleSeo(): string
{
if (App::isLocale('ru')) {
return (string) $this->title_seo['ru'];
}
return (string) $this->title_seo['uz'];
}
public function getBody(): string
{
if (App::isLocale('ru')) {
return (string) $this->body['ru'];
}
return (string) $this->body['uz'];
}
public function getShortBody(): string
{
if (App::isLocale('ru')) {
if (!empty($this->descriptions['ru'])) {
return (string) $this->descriptions['ru'];
}
return (string) $this->short_body['ru'];
}
if (!empty($this->descriptions['uz'])) {
return (string) $this->descriptions['uz'];
}
return (string) $this->short_body['uz'];
}
public function getKeywords(): string
{
if (App::isLocale('ru')) {
if (!empty($this->keywords['ru'])) {
$title = str_replace(' ', ', ', $this->getName());
$keywords = $this->keywords['ru'];
return "{$title}, {$keywords}";
}
}
if (!empty($this->keywords['uz'])) {
$title = str_replace(' ', ', ', $this->getName());
$keywords = $this->keywords['uz'];
return "{$title}, {$keywords}";
}
$title = str_replace(' ', ', ', $this->getName());
$description = str_replace(' ', ', ', $this->getShortBody());
return "{$title}, {$description}";
}
public function getPrice($precision = 0): float
{
return round($this->price * $this->getCurrency(), $precision);
}
public function getPoster(): string
{
if (!empty($this->poster)) {
return Storage::url($this->poster);
}
return config('app.url') . '/images/no_product.jpg';
}
public function getDataSheet()
{
if (!empty($this->data_sheet) and ($this->data_sheet != null and $this->data_sheet != "null")) {
return Storage::url($this->data_sheet);
}
return null;
}
public function getPosterThumb(): string
{
if (!empty($this->poster_thumb)) {
return Storage::url($this->poster_thumb);
}
return config('app.url') . '/images/no_product.jpg';
}
/**
* @return float
*/
public function getDiscountPrice()
{
return round($this->price_discount * $this->getCurrency());
}
public function getOnCreditAttribute(): float
{
$price = $this->getPriceCredit();
$credit = $price / 11;
return abs($credit);
}
public function measurement(): BelongsTo
{
return $this->belongsTo(Measurement::class, 'measurement_id', 'id');
}
public function getPriceCredit(): float
{
return round($this->price_credit * $this->getCurrency());
}
private function pmt(float $rate, int $periods, float $present_value, float $future_value = 0.0, bool $beginning = false): float
{
$when = $beginning ? 1 : 0;
if ($rate == 0) {
return -($future_value + $present_value) / $periods;
}
return -($future_value + ($present_value * pow(1 + $rate, $periods)))
/
((1 + $rate * $when) / $rate * (pow(1 + $rate, $periods) - 1));
}
public function getCurrency(): int
{
$currency = Currency::latest('id', 'desc')->limit(1)->first();
if ($this->currency == 'dollar') {
return $currency->dollar;
} elseif ($this->currency == 'sum') {
return 1;
} else {
return $currency->euro;
}
}
public function getPriceFormat(): string
{
return number_format($this->price, 0, '', ' ');
}
public function getPriceDiscount(): int
{
return (int) $this->price_discount;
}
public function screen(): BelongsTo
{
return $this->belongsTo(Screen::class, 'id', 'product_id');
}
public function discount(): float
{
$a = $this->price;
$b = $this->price_discount;
$x = (($b * 100) / $a) - 100;
return abs($x);
}
public function getDiffDate(): bool
{
$original_date = date_create(Carbon::parse($this->created_at)->format('Y-m-d'));
$now = date_create(Carbon::now()->format('Y-m-d'));
$diff = date_diff($original_date, $now);
if ($diff->format("%a") <= 10) {
return true;
}
return false;
}
public function categories(): BelongsToMany
{
return $this->belongsToMany(Category::class, 'categories_products');
}
public function getSlug(): string
{
return (string) $this->slug;
}
public function isAviable(): bool
{
return $this->published;
}
public function brand(): BelongsTo
{
return $this->belongsTo(Brand::class, 'brand_id', 'id')->withDefault([
'name' => [
'uz' => 'Brand yo`q',
'ru' => 'Бренд нет'
]
]);
}
public function children(): HasOne
{
return $this->hasOne(self::class, 'child_id', 'id');
}
public function childrens(): HasMany
{
return $this->hasMany(self::class, 'child_id', 'id');
}
public function comments(): HasMany
{
return $this->hasMany(Comment::class)->where('publish', true);
}
public function childrensColor(): HasMany
{
return $this->hasMany(self::class, 'child_id', 'id');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function color()
{
return $this->belongsTo(Color::class, 'color_id', 'id');
}
public function screens(): HasMany
{
return $this->hasMany(Screen::class);
}
public function data(): HasOne
{
return $this->hasOne(self::class, 'child_id', 'id');
}
public function product(): BelongsTo
{
return $this->belongsTo(self::class, 'child_id', 'id');
}
public function compilations(): BelongsToMany
{
return $this->belongsToMany(Compilation::class, 'compilation_products');
}
public function getIsFavoriteAttribute(): bool
{
$user = request()->user();
if (!empty($user)) {
$favorite = $this->belongsToMany(User::class, 'products_users')->where('user_id', $user->id)->where('product_id', $this->id)->first();
if (!empty($favorite)) {
return true;
}
}
if (!empty(getAuthUser())) {
$favorite = $this->belongsToMany(User::class, 'products_users')->where('user_id', getAuthUser()->id)->where('product_id', $this->id)->first();
if (!empty($favorite)) {
return true;
}
}
return false;
}
public function getIsAvailableAttribute(): bool
{
if ($this->available && $this->count > 0) {
return true;
}
return false;
}
public function getIsCartAttribute(): bool
{
$user = getAuthUser();
$userId = $user?->id;
$token = request()->header('X-Application-Token');
$cartQuery = Cart::where('product_id', $this->id);
if (isset($userId)) {
$cartQuery->where('user_id', $userId);
$cart = $cartQuery->first();
if ($cart) {
return true;
}
}
if (isset($token)) {
$cartQuery->where('token', $token);
$cart = $cartQuery->first();
if ($cart) {
return true;
}
}
return false;
}
public function getDiffDateAttribute(): bool
{
$original_date = date_create(Carbon::parse($this->created_at)->format('Y-m-d'));
$now = date_create(Carbon::now()->format('Y-m-d'));
$diff = date_diff($original_date, $now);
if ($diff->format("%a") <= 10) {
return true;
}
return false;
}
public function characteristics(): BelongsToMany
{
return $this->belongsToMany(Characteristic::class, 'characteristics_products')->withPivot(['value']);
}
// -- Scopes --
public function scopeBrand($query, $brand_id): mixed
{
return $query->where('brand_id', $brand_id);
}
public function scopeIsAvailable($query): mixed
{
return $query->where('available', true)->where('count', '>', 0);
}
public function scopePublished($query): mixed
{
return $query->where('published', true)->whereNull('deleted_at');
}
public function scopeNotChilds($query): mixed
{
return $query->whereNull('child_id');
}
public function scopeSearchFilter($query, $id, $brand, $category, $published, $article_number, $category_id, $name)
{
return $query->when($id ?? null, function ($query, $id) {
$query->where('id', $id);
})
->whereHas('categories', function ($query) use ($category, $category_id) {
$query->when($category ?? null, function ($query, $category) use ($category_id) {
$query->whereIn('id', $category_id);
});
})->when($published ?? null, function ($query, $published) {
if ($published == 2) {
$query->where('published', false);
} else {
$query->where('published', true);
}
})->when($name ?? null, function ($query, $name) {
$query->where('name->ru', 'ilike', '%' . $name . '%');
})->when($article_number ?? null, function ($query, $article_number) {
$query->where('article_number', $article_number);
})->notChilds();
}
}