Skip to content
Merged
44 changes: 44 additions & 0 deletions database/migrations/2025_08_23_221543_create_pim_group_table.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
public function up(): void
{
Schema::create('pim_group', function (Blueprint $table) {
$table->id();

// Add foreign key for tenant if it's configured in the catalogue config
if (config('eclipse-catalogue.tenancy.model')) {
$tenantClass = config('eclipse-catalogue.tenancy.model');
/** @var \Illuminate\Database\Eloquent\Model $tenant */
$tenant = new $tenantClass;
$table->foreignId(config('eclipse-catalogue.tenancy.foreign_key'))
->constrained($tenant->getTable(), $tenant->getKeyName())
->cascadeOnUpdate()
->cascadeOnDelete();
}

$table->string('code', 50)->nullable();
$table->string('name', 100);
$table->boolean('is_active')->default(true);
$table->boolean('is_browsable')->default(false);
$table->timestamps();

// Create unique index on code
if (config('eclipse-catalogue.tenancy.foreign_key')) {
$table->unique([config('eclipse-catalogue.tenancy.foreign_key'), 'code']);
} else {
$table->unique('code');
}
});
}

public function down(): void
{
Schema::dropIfExists('pim_group');
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
public function up(): void
{
Schema::create('pim_group_has_product', function (Blueprint $table) {
$table->foreignId('product_id')
->constrained('catalogue_products', 'id')
->cascadeOnUpdate()
->cascadeOnDelete();

$table->foreignId('group_id')
->constrained('pim_group', 'id')
->cascadeOnUpdate()
->cascadeOnDelete();

$table->integer('sort')->nullable();

$table->primary(['product_id', 'group_id']);
});
}

public function down(): void
{
Schema::dropIfExists('pim_group_has_product');
}
};
1 change: 1 addition & 0 deletions database/seeders/CatalogueSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public function run(): void
{
$this->call(CategorySeeder::class);
$this->call(ProductTypeSeeder::class);
$this->call(GroupSeeder::class);
$this->call(PropertySeeder::class);
$this->call(ProductSeeder::class);
}
Expand Down
49 changes: 49 additions & 0 deletions database/seeders/GroupSeeder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace Eclipse\Catalogue\Seeders;

use Eclipse\Catalogue\Models\Group;
use Illuminate\Database\Seeder;

class GroupSeeder extends Seeder
{
public function run(): void
{
// Create different groups for each tenant
$tenantModel = config('eclipse-catalogue.tenancy.model');
$tenantFK = config('eclipse-catalogue.tenancy.foreign_key');
$sites = $tenantModel::all();

// Define various group options
$groupOptions = [
['code' => 'featured', 'name' => 'Featured Products', 'is_browsable' => true],
['code' => 'new-arrivals', 'name' => 'New Arrivals', 'is_browsable' => true],
['code' => 'best-sellers', 'name' => 'Best Sellers', 'is_browsable' => true],
['code' => 'sale', 'name' => 'Sale Items', 'is_browsable' => false],
['code' => 'trending', 'name' => 'Trending Now', 'is_browsable' => true],
['code' => 'staff-picks', 'name' => 'Staff Picks', 'is_browsable' => true],
['code' => 'seasonal', 'name' => 'Seasonal Collection', 'is_browsable' => true],
['code' => 'limited-edition', 'name' => 'Limited Edition', 'is_browsable' => true],
['code' => 'clearance', 'name' => 'Clearance Items', 'is_browsable' => false],
['code' => 'premium', 'name' => 'Premium Selection', 'is_browsable' => true],
['code' => 'eco-friendly', 'name' => 'Eco-Friendly', 'is_browsable' => true],
['code' => 'gift-guide', 'name' => 'Gift Guide', 'is_browsable' => true],
];

foreach ($sites as $site) {
// Randomly select 4-6 groups for each tenant
$numGroups = rand(4, 6);
$selectedGroups = collect($groupOptions)->shuffle()->take($numGroups);

foreach ($selectedGroups as $groupData) {
Group::create([
$tenantFK => $site->id,
'code' => $groupData['code'],
'name' => $groupData['name'],
'is_active' => true,
'is_browsable' => $groupData['is_browsable'],
]);
}
}
}
}
45 changes: 44 additions & 1 deletion database/seeders/ProductSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Eclipse\Catalogue\Seeders;

use Eclipse\Catalogue\Models\Category;
use Eclipse\Catalogue\Models\Group;
use Eclipse\Catalogue\Models\Product;
use Eclipse\Catalogue\Models\ProductData;
use Eclipse\Catalogue\Models\ProductType;
Expand All @@ -17,6 +18,7 @@ public function run(): void
{
$this->ensureSampleImagesExist();
$this->ensureProductTypesExist();
$this->ensureGroupsExist();

$productTypes = ProductType::all();

Expand All @@ -33,7 +35,7 @@ public function run(): void

$products = Product::query()->latest('id')->take(100)->get();

foreach ($products as $product) {
foreach ($products as $index => $product) {
if ($tenantFK && $tenantModel && class_exists($tenantModel)) {
$tenants = $tenantModel::all();
foreach ($tenants as $tenant) {
Expand All @@ -50,6 +52,14 @@ public function run(): void
'has_free_delivery' => false,
'category_id' => $categoryId,
]);

// Get groups for this specific tenant
$tenantGroups = Group::where($tenantFK, $tenant->id)->get();
$groupsToAdd = $this->determineGroupsForProduct($index, $tenantGroups);

foreach ($groupsToAdd as $group) {
$group->addProduct($product);
}
}
} else {
$categoryId = Category::query()->inRandomOrder()->value('id');
Expand All @@ -60,10 +70,34 @@ public function run(): void
'has_free_delivery' => false,
'category_id' => $categoryId,
]);

// For non-tenant scenarios, use all groups
$groups = Group::all();
$groupsToAdd = $this->determineGroupsForProduct($index, $groups);
foreach ($groupsToAdd as $group) {
$group->addProduct($product);
}
}
}
}

private function determineGroupsForProduct(int $productIndex, $groups): array
{
$groupsToAdd = [];

// Randomly assign 1-3 groups per product
$numGroupsToAdd = rand(1, min(3, $groups->count()));

// Get random groups for this product
$randomGroups = $groups->random($numGroupsToAdd);

foreach ($randomGroups as $group) {
$groupsToAdd[] = $group;
}

return $groupsToAdd;
}

private function ensureSampleImagesExist(): void
{
Storage::disk('public')->makeDirectory('sample-products');
Expand Down Expand Up @@ -109,4 +143,13 @@ private function ensureProductTypesExist(): void
$this->call(ProductTypeSeeder::class);
}
}

private function ensureGroupsExist(): void
{
$groups = Group::all();

if ($groups->isEmpty()) {
$this->call(GroupSeeder::class);
}
}
}
19 changes: 19 additions & 0 deletions resources/lang/en/group.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

return [
'title' => 'Groups',
'fields' => [
'code' => 'Code',
'name' => 'Name',
'is_active' => 'Active',
'is_browsable' => 'Browsable',
],
'table' => [
'columns' => [
'products' => 'Products',
],
'actions' => [
'sort_products' => 'Sort Products',
],
],
];
19 changes: 19 additions & 0 deletions resources/lang/sl/group.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

return [
'title' => 'Skupine',
'fields' => [
'code' => 'Koda',
'name' => 'Ime',
'is_active' => 'Aktivna',
'is_browsable' => 'Brskanje omogočeno',
],
'table' => [
'columns' => [
'products' => 'Izdelki',
],
'actions' => [
'sort_products' => 'Razvrsti izdelke',
],
],
];
45 changes: 45 additions & 0 deletions src/Factories/GroupFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace Eclipse\Catalogue\Factories;

use Eclipse\Catalogue\Models\Group;
use Illuminate\Database\Eloquent\Factories\Factory;

class GroupFactory extends Factory
{
protected $model = Group::class;

public function definition(): array
{
$tenantFK = config('eclipse-catalogue.tenancy.foreign_key', 'site_id');

return [
$tenantFK => null, // Will be set when creating
'code' => $this->faker->unique()->slug(2),
'name' => $this->faker->words(2, true),
'is_active' => true,
'is_browsable' => false,
];
}

public function inactive(): static
{
return $this->state(fn (array $attributes) => [
'is_active' => false,
]);
}

public function browsable(): static
{
return $this->state(fn (array $attributes) => [
'is_browsable' => true,
]);
}

public function notBrowsable(): static
{
return $this->state(fn (array $attributes) => [
'is_browsable' => false,
]);
}
}
Loading