R product columns
This commit is contained in:
parent
b65706e029
commit
afe7359ea4
|
|
@ -20,7 +20,7 @@ class ProductFactory extends Factory
|
||||||
'sku' => strtoupper($this->faker->bothify('??-####')),
|
'sku' => strtoupper($this->faker->bothify('??-####')),
|
||||||
'type' => 'simple',
|
'type' => 'simple',
|
||||||
'status' => 'published',
|
'status' => 'published',
|
||||||
'visible' => true,
|
'is_visible' => true,
|
||||||
'featured' => false,
|
'featured' => false,
|
||||||
'price' => $this->faker->randomFloat(2, 10, 1000),
|
'price' => $this->faker->randomFloat(2, 10, 1000),
|
||||||
'regular_price' => $this->faker->randomFloat(2, 10, 1000),
|
'regular_price' => $this->faker->randomFloat(2, 10, 1000),
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ return new class extends Migration
|
||||||
if (!Schema::hasTable(config('shop.tables.products', 'products'))) {
|
if (!Schema::hasTable(config('shop.tables.products', 'products'))) {
|
||||||
Schema::create(config('shop.tables.products', 'products'), function (Blueprint $table) {
|
Schema::create(config('shop.tables.products', 'products'), function (Blueprint $table) {
|
||||||
$table->uuid('id')->primary();
|
$table->uuid('id')->primary();
|
||||||
$table->string('name');
|
$table->string('name')->nullable();
|
||||||
$table->string('slug')->unique();
|
$table->string('slug')->unique();
|
||||||
$table->string('sku')->nullable()->unique();
|
$table->string('sku')->nullable()->unique();
|
||||||
$table->text('short_description')->nullable();
|
$table->text('short_description')->nullable();
|
||||||
|
|
@ -40,7 +40,7 @@ return new class extends Migration
|
||||||
$table->boolean('downloadable')->default(false);
|
$table->boolean('downloadable')->default(false);
|
||||||
$table->uuid('parent_id')->nullable();
|
$table->uuid('parent_id')->nullable();
|
||||||
$table->boolean('featured')->default(false);
|
$table->boolean('featured')->default(false);
|
||||||
$table->boolean('visible')->default(true);
|
$table->boolean('is_visible')->default(true);
|
||||||
$table->string('status')->default('draft'); // draft, published, archived
|
$table->string('status')->default('draft'); // draft, published, archived
|
||||||
$table->timestamp('published_at')->nullable();
|
$table->timestamp('published_at')->nullable();
|
||||||
$table->integer('sort_order')->default(0);
|
$table->integer('sort_order')->default(0);
|
||||||
|
|
@ -50,7 +50,7 @@ return new class extends Migration
|
||||||
$table->softDeletes();
|
$table->softDeletes();
|
||||||
|
|
||||||
$table->index(['slug', 'status']);
|
$table->index(['slug', 'status']);
|
||||||
$table->index(['featured', 'visible', 'status']);
|
$table->index(['featured', 'is_visible', 'status']);
|
||||||
$table->index('parent_id');
|
$table->index('parent_id');
|
||||||
$table->foreign('parent_id')->references('id')->on(config('shop.tables.products', 'products'))->onDelete('cascade');
|
$table->foreign('parent_id')->references('id')->on(config('shop.tables.products', 'products'))->onDelete('cascade');
|
||||||
});
|
});
|
||||||
|
|
@ -87,13 +87,13 @@ return new class extends Migration
|
||||||
$table->text('description')->nullable();
|
$table->text('description')->nullable();
|
||||||
$table->uuid('parent_id')->nullable();
|
$table->uuid('parent_id')->nullable();
|
||||||
$table->integer('sort_order')->default(0);
|
$table->integer('sort_order')->default(0);
|
||||||
$table->boolean('visible')->default(true);
|
$table->boolean('is_visible')->default(true);
|
||||||
$table->json('meta')->nullable();
|
$table->json('meta')->nullable();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
$table->softDeletes();
|
$table->softDeletes();
|
||||||
|
|
||||||
$table->index(['parent_id', 'visible']);
|
$table->index(['parent_id', 'is_visible']);
|
||||||
$table->index(['slug', 'visible']);
|
$table->index(['slug', 'is_visible']);
|
||||||
$table->foreign('parent_id')->references('id')->on(config('shop.tables.product_categories', 'product_categories'))->onDelete('cascade');
|
$table->foreign('parent_id')->references('id')->on(config('shop.tables.product_categories', 'product_categories'))->onDelete('cascade');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ $product = Product::create([
|
||||||
'price' => 49.99,
|
'price' => 49.99,
|
||||||
'regular_price' => 49.99,
|
'regular_price' => 49.99,
|
||||||
'status' => 'published',
|
'status' => 'published',
|
||||||
'visible' => true,
|
'is_visible' => true,
|
||||||
'featured' => false,
|
'featured' => false,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
@ -49,7 +49,7 @@ $product = Product::create([
|
||||||
'sku' => 'HEAD-PREM-001',
|
'sku' => 'HEAD-PREM-001',
|
||||||
'type' => 'simple',
|
'type' => 'simple',
|
||||||
'status' => 'published',
|
'status' => 'published',
|
||||||
'visible' => true,
|
'is_visible' => true,
|
||||||
'featured' => true,
|
'featured' => true,
|
||||||
'published_at' => now(),
|
'published_at' => now(),
|
||||||
'sort_order' => 10,
|
'sort_order' => 10,
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ class ShopAddExampleProducts extends Command
|
||||||
[
|
[
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'description' => $description,
|
'description' => $description,
|
||||||
'visible' => true,
|
'is_visible' => true,
|
||||||
'sort_order' => 0,
|
'sort_order' => 0,
|
||||||
'meta' => json_encode((object)[]),
|
'meta' => json_encode((object)[]),
|
||||||
]
|
]
|
||||||
|
|
@ -131,7 +131,7 @@ class ShopAddExampleProducts extends Command
|
||||||
'sku' => 'EX-' . strtoupper($this->faker->bothify('??-####')),
|
'sku' => 'EX-' . strtoupper($this->faker->bothify('??-####')),
|
||||||
'type' => $type,
|
'type' => $type,
|
||||||
'status' => $this->faker->randomElement(['published', 'published', 'published', 'draft']), // mostly published
|
'status' => $this->faker->randomElement(['published', 'published', 'published', 'draft']), // mostly published
|
||||||
'visible' => true,
|
'is_visible' => true,
|
||||||
'featured' => $this->faker->boolean(20), // 20% featured
|
'featured' => $this->faker->boolean(20), // 20% featured
|
||||||
'price' => $onSale ? $regularPrice * 0.8 : $regularPrice,
|
'price' => $onSale ? $regularPrice * 0.8 : $regularPrice,
|
||||||
'regular_price' => $regularPrice,
|
'regular_price' => $regularPrice,
|
||||||
|
|
@ -353,12 +353,13 @@ class ShopAddExampleProducts extends Command
|
||||||
|
|
||||||
foreach ($variations as $index => $variation) {
|
foreach ($variations as $index => $variation) {
|
||||||
$variationProduct = Product::create([
|
$variationProduct = Product::create([
|
||||||
|
'name' => $product->name . ' - ' . $variation,
|
||||||
'slug' => $product->slug . '-' . \Illuminate\Support\Str::slug($variation),
|
'slug' => $product->slug . '-' . \Illuminate\Support\Str::slug($variation),
|
||||||
'sku' => $product->sku . '-' . strtoupper(substr($variation, 0, 1)),
|
'sku' => $product->sku . '-' . strtoupper(substr($variation, 0, 1)),
|
||||||
'type' => 'simple',
|
'type' => 'simple',
|
||||||
'parent_id' => $product->id,
|
'parent_id' => $product->id,
|
||||||
'status' => 'published',
|
'status' => 'published',
|
||||||
'visible' => false, // Variations are not directly visible
|
'is_visible' => false, // Variations are not directly visible
|
||||||
'price' => $product->price + ($index * 5), // Slight price increase per size
|
'price' => $product->price + ($index * 5), // Slight price increase per size
|
||||||
'regular_price' => $product->regular_price + ($index * 5),
|
'regular_price' => $product->regular_price + ($index * 5),
|
||||||
'manage_stock' => true,
|
'manage_stock' => true,
|
||||||
|
|
@ -373,7 +374,7 @@ class ShopAddExampleProducts extends Command
|
||||||
|
|
||||||
ProductAttribute::create([
|
ProductAttribute::create([
|
||||||
'product_id' => $variationProduct->id,
|
'product_id' => $variationProduct->id,
|
||||||
'name' => 'Size',
|
'key' => 'Size',
|
||||||
'value' => $variation,
|
'value' => $variation,
|
||||||
'sort_order' => 0,
|
'sort_order' => 0,
|
||||||
'meta' => json_encode((object)[]),
|
'meta' => json_encode((object)[]),
|
||||||
|
|
@ -387,12 +388,13 @@ class ShopAddExampleProducts extends Command
|
||||||
|
|
||||||
for ($i = 0; $i < $groupSize; $i++) {
|
for ($i = 0; $i < $groupSize; $i++) {
|
||||||
$childProduct = Product::create([
|
$childProduct = Product::create([
|
||||||
|
'name' => $product->name . ' Item ' . ($i + 1),
|
||||||
'slug' => $product->slug . '-item-' . ($i + 1),
|
'slug' => $product->slug . '-item-' . ($i + 1),
|
||||||
'sku' => $product->sku . '-' . ($i + 1),
|
'sku' => $product->sku . '-' . ($i + 1),
|
||||||
'type' => 'simple',
|
'type' => 'simple',
|
||||||
'parent_id' => $product->id,
|
'parent_id' => $product->id,
|
||||||
'status' => 'published',
|
'status' => 'published',
|
||||||
'visible' => false,
|
'is_visible' => false,
|
||||||
'price' => $this->faker->randomFloat(2, 10, 100),
|
'price' => $this->faker->randomFloat(2, 10, 100),
|
||||||
'manage_stock' => true,
|
'manage_stock' => true,
|
||||||
'stock_quantity' => $this->faker->numberBetween(10, 50),
|
'stock_quantity' => $this->faker->numberBetween(10, 50),
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ class Product extends Model implements Purchasable
|
||||||
'downloadable',
|
'downloadable',
|
||||||
'parent_id',
|
'parent_id',
|
||||||
'featured',
|
'featured',
|
||||||
'visible',
|
'is_visible',
|
||||||
'status',
|
'status',
|
||||||
'published_at',
|
'published_at',
|
||||||
'meta',
|
'meta',
|
||||||
|
|
@ -62,7 +62,7 @@ class Product extends Model implements Purchasable
|
||||||
'sale_end' => 'datetime',
|
'sale_end' => 'datetime',
|
||||||
'published_at' => 'datetime',
|
'published_at' => 'datetime',
|
||||||
'featured' => 'boolean',
|
'featured' => 'boolean',
|
||||||
'visible' => 'boolean',
|
'is_visible' => 'boolean',
|
||||||
'low_stock_threshold' => 'integer',
|
'low_stock_threshold' => 'integer',
|
||||||
'sort_order' => 'integer',
|
'sort_order' => 'integer',
|
||||||
];
|
];
|
||||||
|
|
@ -348,7 +348,7 @@ class Product extends Model implements Purchasable
|
||||||
|
|
||||||
public function scopeVisible($query)
|
public function scopeVisible($query)
|
||||||
{
|
{
|
||||||
return $query->where('visible', true)
|
return $query->where('is_visible', true)
|
||||||
->where('status', 'published')
|
->where('status', 'published')
|
||||||
->where(function ($q) {
|
->where(function ($q) {
|
||||||
$q->whereNull('published_at')
|
$q->whereNull('published_at')
|
||||||
|
|
@ -405,7 +405,7 @@ class Product extends Model implements Purchasable
|
||||||
|
|
||||||
public function isVisible(): bool
|
public function isVisible(): bool
|
||||||
{
|
{
|
||||||
if (!$this->visible || $this->status !== 'published') {
|
if (!$this->is_visible || $this->status !== 'published') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,12 @@ class ProductCategory extends Model
|
||||||
'description',
|
'description',
|
||||||
'parent_id',
|
'parent_id',
|
||||||
'sort_order',
|
'sort_order',
|
||||||
'visible',
|
'is_visible',
|
||||||
'meta',
|
'meta',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'visible' => 'boolean',
|
'is_visible' => 'boolean',
|
||||||
'meta' => 'object',
|
'meta' => 'object',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -82,7 +82,7 @@ class ProductCategory extends Model
|
||||||
public function children(): HasMany
|
public function children(): HasMany
|
||||||
{
|
{
|
||||||
return $this->hasMany(self::class, 'parent_id')
|
return $this->hasMany(self::class, 'parent_id')
|
||||||
->where('visible', true)
|
->where('is_visible', true)
|
||||||
->orderBy('sort_order');
|
->orderBy('sort_order');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -94,7 +94,7 @@ class ProductCategory extends Model
|
||||||
|
|
||||||
public function scopeVisible($query)
|
public function scopeVisible($query)
|
||||||
{
|
{
|
||||||
return $query->where('visible', true);
|
return $query->where('is_visible', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function scopeRoots($query)
|
public function scopeRoots($query)
|
||||||
|
|
@ -105,7 +105,7 @@ class ProductCategory extends Model
|
||||||
// Backward compatibility accessor
|
// Backward compatibility accessor
|
||||||
public function getIsVisibleAttribute(): bool
|
public function getIsVisibleAttribute(): bool
|
||||||
{
|
{
|
||||||
return $this->attributes['visible'] ?? true;
|
return $this->attributes['is_visible'] ?? true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getProductCountAttribute(): int
|
public function getProductCountAttribute(): int
|
||||||
|
|
|
||||||
|
|
@ -92,11 +92,11 @@ class ProductCategoryTest extends TestCase
|
||||||
public function it_can_check_visibility()
|
public function it_can_check_visibility()
|
||||||
{
|
{
|
||||||
$visibleCategory = ProductCategory::factory()->create([
|
$visibleCategory = ProductCategory::factory()->create([
|
||||||
'visible' => true,
|
'is_visible' => true,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$hiddenCategory = ProductCategory::factory()->create([
|
$hiddenCategory = ProductCategory::factory()->create([
|
||||||
'visible' => false,
|
'is_visible' => false,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertTrue($visibleCategory->is_visible);
|
$this->assertTrue($visibleCategory->is_visible);
|
||||||
|
|
|
||||||
|
|
@ -275,12 +275,12 @@ class ProductManagementTest extends TestCase
|
||||||
public function it_can_scope_visible_products()
|
public function it_can_scope_visible_products()
|
||||||
{
|
{
|
||||||
Product::factory()->create([
|
Product::factory()->create([
|
||||||
'visible' => true,
|
'is_visible' => true,
|
||||||
'status' => 'published',
|
'status' => 'published',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Product::factory()->create([
|
Product::factory()->create([
|
||||||
'visible' => false,
|
'is_visible' => false,
|
||||||
'status' => 'published',
|
'status' => 'published',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue