Skip to content

Commit 7f0775e

Browse files
committed
chore: groups improvements & tenancy edge case fixes
1 parent e111ed4 commit 7f0775e

8 files changed

Lines changed: 106 additions & 50 deletions

File tree

database/migrations/2025_08_23_221543_create_pim_group_table.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,17 @@ public function up(): void
2222
->cascadeOnDelete();
2323
}
2424

25-
$table->string('code', 50);
25+
$table->string('code', 50)->nullable();
2626
$table->string('name', 100);
2727
$table->boolean('is_active')->default(true);
2828
$table->boolean('is_browsable')->default(false);
2929
$table->timestamps();
3030

31-
// Create unique index on tenant key and code
31+
// Create unique index on code
3232
if (config('eclipse-catalogue.tenancy.foreign_key')) {
3333
$table->unique([config('eclipse-catalogue.tenancy.foreign_key'), 'code']);
34+
} else {
35+
$table->unique('code');
3436
}
3537
});
3638
}

database/migrations/2025_08_23_223125_create_pim_group_has_product_table.php

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,19 @@
99
public function up(): void
1010
{
1111
Schema::create('pim_group_has_product', function (Blueprint $table) {
12-
$table->unsignedBigInteger('product_id');
13-
$table->unsignedBigInteger('group_id');
12+
$table->foreignId('product_id')
13+
->constrained('catalogue_products', 'id')
14+
->cascadeOnUpdate()
15+
->cascadeOnDelete();
16+
17+
$table->foreignId('group_id')
18+
->constrained('pim_group', 'id')
19+
->cascadeOnUpdate()
20+
->cascadeOnDelete();
21+
1422
$table->integer('sort')->nullable();
23+
1524
$table->primary(['product_id', 'group_id']);
16-
$table->foreign('product_id')->references('id')->on('catalogue_products')->onDelete('cascade');
17-
$table->foreign('group_id')->references('id')->on('pim_group')->onDelete('cascade');
1825
});
1926
}
2027

src/Filament/Resources/ProductResource.php

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -433,16 +433,7 @@ public static function table(Table $table): Table
433433
->form([
434434
Select::make('group_id')
435435
->label('Group')
436-
->options(function () {
437-
$currentTenant = \Filament\Facades\Filament::getTenant();
438-
$tenantFK = config('eclipse-catalogue.tenancy.foreign_key', 'site_id');
439-
$query = Group::query()->where('is_active', true);
440-
if ($currentTenant) {
441-
$query->where($tenantFK, $currentTenant->id);
442-
}
443-
444-
return $query->pluck('name', 'id')->toArray();
445-
})
436+
->options(fn () => Group::query()->active()->forCurrentTenant()->pluck('name', 'id')->toArray())
446437
->required()
447438
->searchable(),
448439
])
@@ -468,16 +459,7 @@ public static function table(Table $table): Table
468459
->form([
469460
Select::make('group_id')
470461
->label('Group')
471-
->options(function () {
472-
$currentTenant = \Filament\Facades\Filament::getTenant();
473-
$tenantFK = config('eclipse-catalogue.tenancy.foreign_key', 'site_id');
474-
$query = Group::query()->where('is_active', true);
475-
if ($currentTenant) {
476-
$query->where($tenantFK, $currentTenant->id);
477-
}
478-
479-
return $query->pluck('name', 'id')->toArray();
480-
})
462+
->options(fn () => Group::query()->active()->forCurrentTenant()->pluck('name', 'id')->toArray())
481463
->required()
482464
->searchable(),
483465
])

src/Filament/Resources/ProductResource/Pages/CreateProduct.php

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,36 @@ protected function afterCreate(): void
5555
/** @var Product $product */
5656
$product = $this->record;
5757

58-
// Attach groups per-tenant from tenant_data.*.groups selections
5958
$state = $this->form->getState();
6059
$tenantData = $state['tenant_data'] ?? [];
61-
foreach ($tenantData as $tenantId => $data) {
62-
$groupIds = array_filter(array_map('intval', (array) ($data['groups'] ?? [])));
63-
foreach ($groupIds as $groupId) {
64-
$group = \Eclipse\Catalogue\Models\Group::find($groupId);
65-
$tenantFK = config('eclipse-catalogue.tenancy.foreign_key', 'site_id');
66-
if ($group && (int) $group->getAttribute($tenantFK) === (int) $tenantId) {
60+
61+
$isTenancyEnabled = (bool) config('eclipse-catalogue.tenancy.model');
62+
if ($isTenancyEnabled) {
63+
foreach ($tenantData as $tenantId => $data) {
64+
$groupIds = array_filter(array_map('intval', (array) ($data['groups'] ?? [])));
65+
foreach ($groupIds as $groupId) {
66+
$group = \Eclipse\Catalogue\Models\Group::find($groupId);
67+
$tenantFK = config('eclipse-catalogue.tenancy.foreign_key', 'site_id');
68+
if ($group && (int) $group->getAttribute($tenantFK) === (int) $tenantId) {
69+
$group->addProduct($product);
70+
}
71+
}
72+
}
73+
} else {
74+
$flatGroupIds = [];
75+
if (isset($state['groups'])) {
76+
$flatGroupIds = array_filter(array_map('intval', (array) $state['groups']));
77+
} else {
78+
foreach ($tenantData as $data) {
79+
foreach ((array) ($data['groups'] ?? []) as $id) {
80+
$flatGroupIds[] = (int) $id;
81+
}
82+
}
83+
$flatGroupIds = array_values(array_unique(array_filter($flatGroupIds)));
84+
}
85+
86+
foreach ($flatGroupIds as $groupId) {
87+
if ($group = \Eclipse\Catalogue\Models\Group::find($groupId)) {
6788
$group->addProduct($product);
6889
}
6990
}

src/Filament/Resources/ProductResource/Pages/EditProduct.php

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ protected function mutateFormDataBeforeFill(array $data): array
7777
$data['category_id'] = $recordData->category_id ?? null;
7878
}
7979

80+
$data['groups'] = $this->record->groups()->pluck('pim_group.id')->toArray();
81+
8082
return $data;
8183
}
8284

@@ -114,12 +116,17 @@ protected function handleRecordUpdate(Model $record, array $data): Model
114116

115117
// Sync groups via Group model methods (weak pivot handling) using per-tenant selections
116118
$state = $this->form->getState();
117-
$tenantDataState = $state['tenant_data'] ?? [];
118-
$desiredGroupIds = collect($tenantDataState)
119-
->flatMap(fn ($td) => array_map('intval', (array) ($td['groups'] ?? [])))
120-
->unique()
121-
->values()
122-
->toArray();
119+
120+
$tenantFK = config('eclipse-catalogue.tenancy.foreign_key');
121+
if ($tenantFK) {
122+
$desiredGroupIds = collect($tenantData)
123+
->flatMap(fn ($td) => array_map('intval', (array) ($td['groups'] ?? [])))
124+
->unique()
125+
->values()
126+
->toArray();
127+
} else {
128+
$desiredGroupIds = array_values(array_unique(array_map('intval', (array) ($state['groups'] ?? []))));
129+
}
123130

124131
$currentGroupIds = $record->groups()->pluck('pim_group.id')->map(fn ($id) => (int) $id)->toArray();
125132
$toAttach = array_values(array_diff($desiredGroupIds, $currentGroupIds));

src/Livewire/TenantSwitcher.php

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,20 @@ public static function make(string $fieldName = 'selected_tenant'): Component
7070
->default($currentTenant?->id)
7171
->selectablePlaceholder(false)
7272
->live()
73+
// Ensure we have a previous-tenant tracker from the start
74+
->afterStateHydrated(function ($state, callable $set) {
75+
$set('_previous_tenant', $state);
76+
})
7377
->afterStateUpdated(function ($state, callable $set, callable $get, $livewire) {
74-
// Get previous tenant from a tracking field
78+
// Snapshot the full sub-state of the tenant we're leaving
7579
$previousTenant = $get('_previous_tenant');
80+
$fromTenant = $previousTenant ?: $get('selected_tenant');
7681

77-
// Store current tenant data before switching
78-
if ($previousTenant && $previousTenant != $state) {
79-
$currentData = $get("tenant_data.{$previousTenant}") ?? [];
82+
if ($fromTenant && $fromTenant != $state) {
83+
$currentData = $get("tenant_data.{$fromTenant}") ?? [];
8084

8185
$allTenantData = $get('all_tenant_data') ?? [];
82-
$allTenantData[$previousTenant] = $currentData;
86+
$allTenantData[$fromTenant] = $currentData;
8387
$set('all_tenant_data', $allTenantData);
8488
}
8589

@@ -127,7 +131,21 @@ public static function makeWithOptions(
127131
->default($currentTenant?->id)
128132
->selectablePlaceholder(false)
129133
->live()
134+
->afterStateHydrated(function ($state, callable $set) {
135+
$set('_previous_tenant', $state);
136+
})
130137
->afterStateUpdated(function ($state, callable $set, callable $get, $livewire) {
138+
$previousTenant = $get('_previous_tenant');
139+
$fromTenant = $previousTenant ?: $get('selected_tenant');
140+
141+
if ($fromTenant && $fromTenant != $state) {
142+
$currentData = $get("tenant_data.{$fromTenant}") ?? [];
143+
$allTenantData = $get('all_tenant_data') ?? [];
144+
$allTenantData[$fromTenant] = $currentData;
145+
$set('all_tenant_data', $allTenantData);
146+
}
147+
148+
$set('_previous_tenant', $state);
131149
$livewire->dispatch('tenant-changed', $state);
132150
});
133151

src/Models/Group.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Eclipse\Catalogue\Models;
44

55
use Eclipse\Catalogue\Factories\GroupFactory;
6+
use Illuminate\Database\Eloquent\Builder;
67
use Illuminate\Database\Eloquent\Factories\HasFactory;
78
use Illuminate\Database\Eloquent\Model;
89
use Illuminate\Database\Eloquent\Relations\BelongsTo;
@@ -27,6 +28,29 @@ class Group extends Model
2728
'is_browsable' => 'boolean',
2829
];
2930

31+
/**
32+
* Scope: only active groups.
33+
*/
34+
public function scopeActive(Builder $query): Builder
35+
{
36+
return $query->where('is_active', true);
37+
}
38+
39+
/**
40+
* Scope: restrict by current tenant if tenancy is enabled and a tenant is selected.
41+
*/
42+
public function scopeForCurrentTenant(Builder $query): Builder
43+
{
44+
$tenantFK = config('eclipse-catalogue.tenancy.foreign_key');
45+
$tenant = \Filament\Facades\Filament::getTenant();
46+
47+
if ($tenantFK && $tenant) {
48+
$query->where($tenantFK, $tenant->id);
49+
}
50+
51+
return $query;
52+
}
53+
3054
/**
3155
* Include the tenant foreign key in fillable when tenancy is on.
3256
*/

src/Traits/HandlesTenantData.php

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,7 @@ protected function storeCurrentTenantData(): void
4242
$selectedTenant = $formData['selected_tenant'] ?? null;
4343

4444
if ($selectedTenant && config('eclipse-catalogue.tenancy.foreign_key')) {
45-
$currentData = [];
46-
47-
// Build current data from tenant flags
48-
foreach ($this->getFormTenantFlags() as $flag) {
49-
$currentData[$flag] = $formData['tenant_data'][$selectedTenant][$flag] ?? $this->getDefaultValueForFlag($flag);
50-
}
45+
$currentData = $formData['tenant_data'][$selectedTenant] ?? [];
5146

5247
$allTenantData = $formData['all_tenant_data'] ?? [];
5348
$allTenantData[$selectedTenant] = $currentData;

0 commit comments

Comments
 (0)