wip
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Ecommerce\Product\Product\Concerns;
|
||||
|
||||
use Laravel\Nova\Nova;
|
||||
|
||||
trait ProductFrontEndHelpers
|
||||
{
|
||||
/**
|
||||
* Show page
|
||||
*/
|
||||
public function showPage(): string
|
||||
{
|
||||
return route('web.products.show', ['product' => $this->slug]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Nova page
|
||||
*/
|
||||
public function novaPage(): string
|
||||
{
|
||||
return Nova::url('/resources/products');
|
||||
}
|
||||
|
||||
/**
|
||||
* Nova detail page
|
||||
*/
|
||||
public function novaDetailPage(): string
|
||||
{
|
||||
return Nova::url('/resources/products/'.$this->id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Ecommerce\Product\Product\Concerns;
|
||||
|
||||
use Spatie\Image\Manipulations;
|
||||
use Spatie\MediaLibrary\MediaCollections\Models\Media;
|
||||
|
||||
trait ProductMedia
|
||||
{
|
||||
/**
|
||||
* Media collections
|
||||
*/
|
||||
public function registerMediaCollections(): void
|
||||
{
|
||||
$this->addMediaCollection('uploads')
|
||||
->useFallbackUrl(url('/assets/web/images/05.jpg'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Media Conversions
|
||||
*/
|
||||
public function registerMediaConversions(?Media $media = null): void
|
||||
{
|
||||
$this->addMediaConversion('thumb200x200')
|
||||
->fit(Manipulations::FIT_CONTAIN, 200, 200);
|
||||
|
||||
$this->addMediaConversion('thumb400x400')
|
||||
->fit(Manipulations::FIT_CONTAIN, 400, 400);
|
||||
|
||||
$this->addMediaConversion('thumb720x720')
|
||||
->fit(Manipulations::FIT_CONTAIN, 720, 720);
|
||||
|
||||
$this->addMediaConversion('thumb800x800')
|
||||
->fit(Manipulations::FIT_CONTAIN, 800, 800);
|
||||
|
||||
$this->addMediaConversion('thumb1200x1200')
|
||||
->fit(Manipulations::FIT_CONTAIN, 1200, 1200);
|
||||
|
||||
$this->addMediaConversion('thumb288x431')
|
||||
->fit(Manipulations::FIT_CONTAIN, 288, 431);
|
||||
|
||||
$this->addMediaConversion('thumb270x350')
|
||||
->fit(Manipulations::FIT_CONTAIN, 270, 350);
|
||||
}
|
||||
|
||||
/**
|
||||
* Thumbnail
|
||||
*/
|
||||
public function thumbnail(string $size = '200x200'): string
|
||||
{
|
||||
return $this->getFirstMediaUrl('uploads', 'thumb'.$size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image when hovered (returns second image)
|
||||
*/
|
||||
public function getHoverImage(string $size = '270x350'): string
|
||||
{
|
||||
$media = $this->getMedia('uploads');
|
||||
$image_count = $media->count();
|
||||
|
||||
if ($image_count == 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return ($image_count == 1)
|
||||
? $media[0]->getUrl('thumb'.$size)
|
||||
: $media[1]->getUrl('thumb'.$size);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,436 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Ecommerce\Product\Product\Concerns;
|
||||
|
||||
use App\Models\Ecommerce\Product\Property\ProductProperty;
|
||||
use Illuminate\Support\Facades\Blade;
|
||||
|
||||
trait ProductProperties
|
||||
{
|
||||
/**
|
||||
* Check if given product has given property
|
||||
*/
|
||||
public function containsProperty(string $property): bool
|
||||
{
|
||||
return $this->properties->pluck('attribute.slug')->contains($property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get product property
|
||||
*/
|
||||
public function getProperty(string $name): ?ProductProperty
|
||||
{
|
||||
return $this->properties->first(fn ($property) => $property->attribute->slug === $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if product has color variants
|
||||
*/
|
||||
public function hasColorVariants(): bool
|
||||
{
|
||||
return $this->containsProperty('colour');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get product color property
|
||||
*/
|
||||
public function getColorProperty(): ?ProductProperty
|
||||
{
|
||||
return $this->getProperty('colour');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get product color property
|
||||
*/
|
||||
public function getSizeProperty(): ?ProductProperty
|
||||
{
|
||||
return $this->getProperty('size');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get color value of product
|
||||
*/
|
||||
public function getColorValue(): ?string
|
||||
{
|
||||
$colorProperty = $this->getColorProperty();
|
||||
|
||||
return $colorProperty ? $colorProperty->values->first()?->real_value : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get size value
|
||||
*/
|
||||
public function getSizeValue(): ?string
|
||||
{
|
||||
$sizeProperty = $this->getSizeProperty();
|
||||
|
||||
return $sizeProperty ? $sizeProperty->values->first()?->real_value : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if product has a color.
|
||||
*/
|
||||
public function hasColor(): bool
|
||||
{
|
||||
return $this->hasPropertyWithSlug('colour');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if product has a size.
|
||||
*/
|
||||
public function hasSize(): bool
|
||||
{
|
||||
return $this->hasPropertyWithSlug('size');
|
||||
}
|
||||
|
||||
/**
|
||||
* Color property
|
||||
*/
|
||||
public function getColor(): string
|
||||
{
|
||||
$product = 'productColor'.$this->id;
|
||||
|
||||
if (temp_cache($product)) {
|
||||
return temp_cache($product);
|
||||
}
|
||||
|
||||
cache()->put(
|
||||
key: 'productColor'.$this->id,
|
||||
value: $this->getPropertyValueBySlug('colour'),
|
||||
);
|
||||
|
||||
return temp_cache($product);
|
||||
}
|
||||
|
||||
/**
|
||||
* Size property
|
||||
*/
|
||||
public function getSize(): string
|
||||
{
|
||||
$product = 'productSize'.$this->id;
|
||||
|
||||
if (temp_cache($product)) {
|
||||
return temp_cache($product);
|
||||
}
|
||||
|
||||
cache()->put(
|
||||
'productSize'.$this->id,
|
||||
$this->getPropertyValueBySlug('size'),
|
||||
);
|
||||
|
||||
return temp_cache($product);
|
||||
}
|
||||
|
||||
/**
|
||||
* Color variants
|
||||
*/
|
||||
public function colorVariants(): array
|
||||
{
|
||||
if (temp_cache('productColorVariants')) {
|
||||
return temp_cache('productColorVariants');
|
||||
}
|
||||
|
||||
$this->loadMissing(['media', 'properties', 'variations' => ['media', 'properties']]);
|
||||
|
||||
$colorVariants = collect();
|
||||
|
||||
// Add parent product
|
||||
$colorVariants->push([
|
||||
'slug' => $this->slug,
|
||||
'id' => $this->id,
|
||||
'image' => $this->thumbnail(),
|
||||
'color' => $this->getColor(),
|
||||
]);
|
||||
|
||||
$this->variations->each(function ($variation) use ($colorVariants) {
|
||||
$colorVariants->push([
|
||||
'slug' => $variation->slug,
|
||||
'id' => $variation->id,
|
||||
'image' => $variation->thumbnail(),
|
||||
'color' => $variation->getColor(),
|
||||
]);
|
||||
});
|
||||
|
||||
cache()->put(
|
||||
'productColorVariants',
|
||||
$colorVariants->uniqueStrict('color')->toArray(),
|
||||
);
|
||||
|
||||
return $colorVariants->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a property with the given attribute slug exists
|
||||
*/
|
||||
protected function hasPropertyWithSlug(string $slug): bool
|
||||
{
|
||||
if ($this->relationLoaded('properties')) {
|
||||
return $this->checkLoadedPropertiesForSlug($slug);
|
||||
}
|
||||
|
||||
return $this->checkDatabaseForPropertySlug($slug);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check loaded properties for attribute slug
|
||||
*/
|
||||
protected function checkLoadedPropertiesForSlug(string $slug): bool
|
||||
{
|
||||
foreach ($this->properties as $property) {
|
||||
if ($property->attribute->slug === $slug) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check database for attribute slug
|
||||
*/
|
||||
protected function checkDatabaseForPropertySlug(string $slug): bool
|
||||
{
|
||||
return $this->properties()
|
||||
->where('attribute.slug', $slug)
|
||||
->exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get property value by slug
|
||||
*/
|
||||
public function getPropertyValueBySlug(string $slug): string
|
||||
{
|
||||
return $this->properties->firstWhere('attribute.slug', 'colour')->values->first()->real_value ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get size variants available for given color
|
||||
*/
|
||||
public function getSizeVariantsForColor(): array
|
||||
{
|
||||
if (temp_cache('productSizeVariantsForColor')) {
|
||||
return temp_cache('productSizeVariantsForColor');
|
||||
}
|
||||
|
||||
if ($this->parent_id) {
|
||||
return $this->childSizeVariantsForColor();
|
||||
}
|
||||
|
||||
$this->loadMissing(['properties', 'variations', 'variations.properties']);
|
||||
|
||||
$properties = $this->properties;
|
||||
$variations = $this->variations;
|
||||
|
||||
$productSize = [];
|
||||
$matchingProducts = [];
|
||||
|
||||
foreach ($properties as $property) {
|
||||
if ($property->attribute->slug === 'size') {
|
||||
$productSize = $property->values->first()->real_value;
|
||||
|
||||
$productSize = [
|
||||
'slug' => $this->slug,
|
||||
'id' => $this->id,
|
||||
'size' => $productSize,
|
||||
'parent_id' => null,
|
||||
];
|
||||
}
|
||||
|
||||
if ($property->attribute->slug === 'colour') {
|
||||
// Color found
|
||||
$productColor = $property->values->first()->real_value;
|
||||
|
||||
// Get All Sizes
|
||||
$variationAllSizes = [];
|
||||
|
||||
// Iterate over to find same colors in variants
|
||||
foreach ($variations as $variation) {
|
||||
foreach ($variation->properties as $variationProperty) {
|
||||
|
||||
if ($variationProperty->attribute->slug === 'size') {
|
||||
$productSize = $variationProperty->values->first()->real_value;
|
||||
|
||||
$variationAllSizes[] = [
|
||||
'slug' => $variation->slug,
|
||||
'id' => $variation->id,
|
||||
'parent_id' => $variation->parent_id,
|
||||
'size' => $productSize,
|
||||
];
|
||||
}
|
||||
|
||||
if ($variationProperty->attribute->slug === 'colour') {
|
||||
// If colors match, append to array
|
||||
$variationColor = $variationProperty->values->first()->real_value;
|
||||
|
||||
if ($productColor === $variationColor) {
|
||||
$matchingProducts[] = [
|
||||
'slug' => $variation->slug,
|
||||
'id' => $variation->id,
|
||||
'color' => $productColor,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} /* Color end */
|
||||
}
|
||||
|
||||
$result = collect();
|
||||
$result->push($productSize);
|
||||
|
||||
collect($variationAllSizes)->whereIn('id', collect($matchingProducts)->pluck('id'))
|
||||
->each(function ($variationSize) use ($result) {
|
||||
$result->push($variationSize);
|
||||
});
|
||||
|
||||
cache()->put(
|
||||
'productSizeVariantsForColor',
|
||||
$result->toArray(),
|
||||
);
|
||||
|
||||
return $result->toArray();
|
||||
}
|
||||
|
||||
public function childSizeVariantsForColor(): array
|
||||
{
|
||||
$this->loadMissing(['properties']);
|
||||
|
||||
$properties = $this->properties;
|
||||
$parent = $this->parent;
|
||||
$parent->load(['properties', 'variations', 'variations.properties']);
|
||||
$variations = $parent->variations;
|
||||
|
||||
$productSize = [];
|
||||
$matchingProducts = [];
|
||||
|
||||
foreach ($properties as $property) {
|
||||
if ($property->attribute->slug === 'size') {
|
||||
$productSize = $property->values->first()->real_value;
|
||||
|
||||
$productSize = [
|
||||
'slug' => $this->slug,
|
||||
'id' => $this->id,
|
||||
'size' => $productSize,
|
||||
'parent_id' => $this->parent_id,
|
||||
];
|
||||
}
|
||||
|
||||
if ($property->attribute->slug === 'colour') {
|
||||
// Color found
|
||||
$productColor = $property->values->first()->real_value;
|
||||
|
||||
// Get All Sizes
|
||||
$variationAllSizes = [];
|
||||
|
||||
// Iterate over to find same colors in variants
|
||||
foreach ($variations as $variation) {
|
||||
if ($variation->id === $this->id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($variation->properties as $variationProperty) {
|
||||
|
||||
if ($variationProperty->attribute->slug === 'size') {
|
||||
$productSize = $variationProperty->values->first()->real_value;
|
||||
|
||||
$variationAllSizes[] = [
|
||||
'slug' => $variation->slug,
|
||||
'id' => $variation->id,
|
||||
'parent_id' => $variation->parent_id,
|
||||
'size' => $productSize,
|
||||
];
|
||||
}
|
||||
|
||||
if ($variationProperty->attribute->slug === 'colour') {
|
||||
// If colors match, append to array
|
||||
$variationColor = $variationProperty->values->first()->real_value;
|
||||
|
||||
if ($productColor === $variationColor) {
|
||||
$matchingProducts[] = [
|
||||
'slug' => $variation->slug,
|
||||
'id' => $variation->id,
|
||||
'color' => $productColor,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} /* Color end */
|
||||
}
|
||||
|
||||
$result = collect();
|
||||
$result->push($productSize);
|
||||
|
||||
collect($variationAllSizes)->whereIn('id', collect($matchingProducts)->pluck('id'))
|
||||
->each(function ($variationSize) use ($result) {
|
||||
$result->push($variationSize);
|
||||
});
|
||||
|
||||
return $result->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* All values of product properties
|
||||
*/
|
||||
public function allValuesOfProperties(): array
|
||||
{
|
||||
return $this->properties->flatMap(function ($property) {
|
||||
return $property->values->map(function ($value) {
|
||||
return $value->real_value;
|
||||
})->filter();
|
||||
})->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Name with properties
|
||||
*/
|
||||
public function nameWithProperties(): string
|
||||
{
|
||||
$properties = $this->allValuesOfProperties();
|
||||
|
||||
return sprintf(
|
||||
'%s %s %s',
|
||||
$this->name,
|
||||
count($properties) > 0 ? '-' : '',
|
||||
Blade::render('
|
||||
@foreach($datas as $data)
|
||||
<strong>{{ $data }}{{ $loop->last ? "" : "," }}</strong>
|
||||
@endforeach
|
||||
', ['datas' => $properties])
|
||||
);
|
||||
}
|
||||
|
||||
public function getSizeVariants(): array
|
||||
{
|
||||
$sizeVariants = [];
|
||||
|
||||
// Add parent product
|
||||
$sizeVariants[] = [
|
||||
'slug' => $this->slug,
|
||||
'id' => $this->id,
|
||||
'image' => $this->thumbnail(),
|
||||
'images_hd' => $this->getMedia('uploads')->map(fn ($media) => $media->getUrl('thumb720x720')),
|
||||
'size' => $this->getSizeValue(),
|
||||
];
|
||||
|
||||
$this->variations->each(function ($variation) use (&$sizeVariants) {
|
||||
$variationSize = $variation->getSizeValue();
|
||||
|
||||
if ($variationSize && ! keyValueExistsInArray(datas: $sizeVariants, key: 'size', value: $variationSize)) {
|
||||
$sizeVariants[] = [
|
||||
'slug' => $variation->slug,
|
||||
'id' => $variation->id,
|
||||
'image' => $variation->thumbnail(),
|
||||
'images_hd' => $variation->getMedia('uploads')->map(fn ($media) => $media->getUrl('thumb720x720')),
|
||||
'size' => $variationSize,
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
return $sizeVariants;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Ecommerce\Product\Product\Concerns;
|
||||
|
||||
use App\Models\Common\Comment;
|
||||
use App\Models\Ecommerce\Channel\Channel;
|
||||
use App\Models\Ecommerce\Product\Brand\Brand;
|
||||
use App\Models\Ecommerce\Product\Cart\Cart;
|
||||
use App\Models\Ecommerce\Product\Category\Category;
|
||||
use App\Models\Ecommerce\Product\Collection\Collection;
|
||||
use App\Models\Ecommerce\Product\Inventory\Inventory;
|
||||
use App\Models\Ecommerce\Product\Product\Product;
|
||||
use App\Models\Ecommerce\Product\Property\ProductProperty;
|
||||
use App\Models\Ecommerce\Product\Review\Review;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphToMany;
|
||||
|
||||
trait ProductRelationships
|
||||
{
|
||||
/**
|
||||
* Product variations
|
||||
*/
|
||||
public function variations(): HasMany
|
||||
{
|
||||
return $this->hasMany(Product::class, 'parent_id');
|
||||
}
|
||||
|
||||
/**
|
||||
+ * Parent
|
||||
+ */
|
||||
public function parent(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Product::class, 'parent_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Related Channels
|
||||
*/
|
||||
public function channels(): MorphToMany
|
||||
{
|
||||
return $this->morphedByMany(Channel::class, 'productable', 'product_has_relations');
|
||||
}
|
||||
|
||||
/**
|
||||
* Firt channel
|
||||
*/
|
||||
public function owner(): ?Channel
|
||||
{
|
||||
return $this->relationLoaded('channels')
|
||||
? $this->channels->first()
|
||||
: $this->channels()->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Related products (similar)
|
||||
*/
|
||||
public function relatedProducts(): MorphToMany
|
||||
{
|
||||
return $this->morphedByMany(Product::class, 'productable', 'product_has_relations');
|
||||
}
|
||||
|
||||
/**
|
||||
* Related categories
|
||||
*/
|
||||
public function categories(): MorphToMany
|
||||
{
|
||||
return $this->morphedByMany(Category::class, 'productable', 'product_has_relations');
|
||||
}
|
||||
|
||||
/**
|
||||
* Related Collections
|
||||
*/
|
||||
public function collections(): MorphToMany
|
||||
{
|
||||
return $this->morphedByMany(Collection::class, 'productable', 'product_has_relations');
|
||||
}
|
||||
|
||||
/**
|
||||
* Related Brand
|
||||
*/
|
||||
public function brand(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Brand::class, 'brand_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Product Properties, same as attribtues
|
||||
*
|
||||
* (size, color, material, ..)
|
||||
*/
|
||||
public function properties(): HasMany
|
||||
{
|
||||
return $this->hasMany(ProductProperty::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Related inventories
|
||||
*/
|
||||
public function inventories(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Inventory::class)
|
||||
->withPivot('stock');
|
||||
}
|
||||
|
||||
/**
|
||||
* Carts
|
||||
*/
|
||||
public function carts(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Cart::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Product's review
|
||||
*/
|
||||
public function reviews(): HasMany
|
||||
{
|
||||
return $this->hasMany(Review::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Product's comments
|
||||
*/
|
||||
public function comments(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Comment::class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Ecommerce\Product\Product\Concerns;
|
||||
|
||||
trait ProductScopeQueries
|
||||
{
|
||||
/**
|
||||
* Visable products scope
|
||||
*
|
||||
* @param mixed $query
|
||||
*/
|
||||
public function scopeVisable($query): void
|
||||
{
|
||||
$query->where('is_visible', true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Ecommerce\Product\Product\Concerns;
|
||||
|
||||
trait ProductStates
|
||||
{
|
||||
/**
|
||||
* Check if product is new (one week range)
|
||||
*/
|
||||
public function isNew(): bool
|
||||
{
|
||||
return $this->created_at->greaterThan(now()->subWeek());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Ecommerce\Product\Product\Concerns;
|
||||
|
||||
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
||||
|
||||
trait ProductStock
|
||||
{
|
||||
/**
|
||||
* Inventory history
|
||||
*/
|
||||
public function inventoryHistories(): MorphMany
|
||||
{
|
||||
return $this->morphMany(InventoryHistory::class, 'stockable')->orderBy('created_at', 'desc');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Ecommerce\Product\Product\Concerns;
|
||||
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Spatie\Sluggable\SlugOptions;
|
||||
|
||||
trait ProductTransformers
|
||||
{
|
||||
/**
|
||||
* Get the options for generating the slug.
|
||||
*/
|
||||
public function getSlugOptions(): SlugOptions
|
||||
{
|
||||
return SlugOptions::create()
|
||||
->generateSlugsFrom('name')
|
||||
->saveSlugsTo('slug');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get discount difference
|
||||
*
|
||||
* @return int|float
|
||||
*/
|
||||
public function discountDifference(): Attribute
|
||||
{
|
||||
return Attribute::make(get: fn () => $this->caluculateDiscountDifference());
|
||||
}
|
||||
|
||||
/**
|
||||
* Discount percentage
|
||||
*/
|
||||
public function discountPercentage()
|
||||
{
|
||||
return number_format(($this->caluculateDiscountDifference() * 100) / $this->old_price_amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Caluculate Discount Difference
|
||||
*/
|
||||
public function caluculateDiscountDifference(int|float|null $price_amount = null): float
|
||||
{
|
||||
return $this->old_price_amount ? $this->old_price_amount - ($price_amount ?: $this->price_amount) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Full name
|
||||
*/
|
||||
public function fullName(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: function () {
|
||||
$brand = $this->brand ? "({$this->brand->name})" : '';
|
||||
|
||||
return $this->name.$brand.$this->colour.$this->size;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool backorder
|
||||
*/
|
||||
public function backOrder(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn () => $this->options->get('back_order')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string weight_value
|
||||
*/
|
||||
public function weightValue(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn () => $this->options->get('weight_value')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string weight_unit
|
||||
*/
|
||||
public function weightUnit(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn () => $this->options->get('weight_unit')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string height_value
|
||||
*/
|
||||
public function heightValue(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn () => $this->options->get('height_value')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string height_unit
|
||||
*/
|
||||
public function heightUnit(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn () => $this->options->get('height_unit')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string width_value
|
||||
*/
|
||||
public function widthValue(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn () => $this->options->get('width_value')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string width_unit
|
||||
*/
|
||||
public function widthUnit(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn () => $this->options->get('width_unit')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string depth_value
|
||||
*/
|
||||
public function depthValue(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn () => $this->options->get('depth_value')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string depth_unit
|
||||
*/
|
||||
public function depthUnit(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn () => $this->options->get('depth_unit')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string volume_value
|
||||
*/
|
||||
public function volumeValue(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn () => $this->options->get('volume_value')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string volume_unit
|
||||
*/
|
||||
public function volumeUnit(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn () => $this->options->get('volume_unit')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flexible Content
|
||||
*/
|
||||
// public function flexibleContent(): Attribute
|
||||
// {
|
||||
// return Attribute::make(
|
||||
// get: fn () => $this->flexible('flexible-content')
|
||||
// );
|
||||
// }
|
||||
}
|
||||
121
app/Models/Ecommerce/Product/Product/Product.php
Normal file
121
app/Models/Ecommerce/Product/Product/Product.php
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Ecommerce\Product\Product;
|
||||
|
||||
use App\Models\Concerns\HasSchemalessAttributes;
|
||||
use App\Models\Ecommerce\Product\Product\Concerns\ProductFrontEndHelpers;
|
||||
use App\Models\Ecommerce\Product\Product\Concerns\ProductMedia;
|
||||
use App\Models\Ecommerce\Product\Product\Concerns\ProductProperties;
|
||||
use App\Models\Ecommerce\Product\Product\Concerns\ProductRelationships;
|
||||
use App\Models\Ecommerce\Product\Product\Concerns\ProductScopeQueries;
|
||||
use App\Models\Ecommerce\Product\Product\Concerns\ProductStates;
|
||||
use App\Models\Ecommerce\Product\Product\Concerns\ProductStock;
|
||||
use App\Models\Ecommerce\Product\Product\Concerns\ProductTransformers;
|
||||
use CyrildeWit\EloquentViewable\Contracts\Viewable;
|
||||
use CyrildeWit\EloquentViewable\InteractsWithViews;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Spatie\MediaLibrary\HasMedia;
|
||||
use Spatie\MediaLibrary\InteractsWithMedia;
|
||||
use Spatie\Sluggable\HasSlug;
|
||||
|
||||
class Product extends Model implements HasMedia, Viewable
|
||||
{
|
||||
/**
|
||||
* Has factory (laravel default)
|
||||
*/
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* Has Schemaless Attributes (spatie/laravel-schemaless-attributes)
|
||||
*/
|
||||
use HasSchemalessAttributes;
|
||||
|
||||
/**
|
||||
* Has Slug (spatie/laravel-sluggable)
|
||||
*/
|
||||
use HasSlug;
|
||||
|
||||
/**
|
||||
* Interacts with media (spatie/laravel-medialibrary)
|
||||
*/
|
||||
use InteractsWithMedia;
|
||||
|
||||
/**
|
||||
* Interacts with views (cyrildewit/eloquent-viewable)
|
||||
*/
|
||||
use InteractsWithViews;
|
||||
|
||||
/**
|
||||
* Product helpers for front end
|
||||
*/
|
||||
use ProductFrontEndHelpers;
|
||||
|
||||
/**
|
||||
* Media interactions
|
||||
*/
|
||||
use ProductMedia {
|
||||
ProductMedia::registerMediaCollections insteadof InteractsWithMedia;
|
||||
ProductMedia::registerMediaConversions insteadof InteractsWithMedia;
|
||||
}
|
||||
|
||||
/**
|
||||
* Product properties (attributes[EAV])
|
||||
*/
|
||||
use ProductProperties;
|
||||
|
||||
/**
|
||||
* Product relationships
|
||||
*/
|
||||
use ProductRelationships;
|
||||
|
||||
/**
|
||||
* Product scope queries
|
||||
*/
|
||||
use ProductScopeQueries;
|
||||
|
||||
/**
|
||||
* Product states (new, featured, ...)
|
||||
*/
|
||||
use ProductStates;
|
||||
|
||||
/**
|
||||
* Products stocks
|
||||
*/
|
||||
use ProductStock;
|
||||
|
||||
/**
|
||||
* Interacts with media (whitecube/nova-flexible-content)
|
||||
*/
|
||||
// use HasFlexible;
|
||||
|
||||
/**
|
||||
* Product Data Transformers
|
||||
*/
|
||||
use ProductTransformers;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*/
|
||||
protected $fillable = [
|
||||
'id',
|
||||
'parent_id',
|
||||
'brand_id',
|
||||
'name',
|
||||
'slug',
|
||||
'description',
|
||||
'sku',
|
||||
'barcode',
|
||||
'stock',
|
||||
'security_stock',
|
||||
'cost_amount',
|
||||
'price_amount',
|
||||
'old_price_amount',
|
||||
'seo_title',
|
||||
'seo_description',
|
||||
'options',
|
||||
'is_visible',
|
||||
'colour',
|
||||
'size',
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user