567 lines
15 KiB
PHP
Executable File
567 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)) {
|
|
if (in_array(config('filesystems.default'), ['s3', 'minio'])) {
|
|
return Storage::temporaryUrl(
|
|
$this->poster,
|
|
Date::now()->addMinutes(5)
|
|
);
|
|
}
|
|
return config('app.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")) {
|
|
if (in_array(config('filesystems.default'), ['s3', 'minio'])) {
|
|
return Storage::temporaryUrl(
|
|
$this->data_sheet,
|
|
Date::now()->addMinutes(5)
|
|
);
|
|
}
|
|
return config('app.url') . '/' . $this->data_sheet;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public function getPosterThumb(): string
|
|
{
|
|
if (!empty($this->poster_thumb)) {
|
|
if (in_array(config('filesystems.default'), ['s3', 'minio'])) {
|
|
return Storage::temporaryUrl(
|
|
$this->poster_thumb,
|
|
Date::now()->addMinutes(5)
|
|
);
|
|
}
|
|
return config('app.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();
|
|
}
|
|
}
|