Fix sort_order: sequential 1,2,3 + renormalize after every save
- saving: always shift >= new position by +1 (no conflict check needed) - saved: renormalize all records to 1, 2, 3... via direct DB update (no model events triggered) to close any gaps left by the move - Migration updated to use step 1 instead of 10 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ namespace App\Models\Tenant;
|
|||||||
use App\Models\Concerns\BelongsToTenant;
|
use App\Models\Concerns\BelongsToTenant;
|
||||||
use App\Models\Scopes\TenantScope;
|
use App\Models\Scopes\TenantScope;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
class LaborCategory extends Model
|
class LaborCategory extends Model
|
||||||
{
|
{
|
||||||
@@ -16,26 +17,31 @@ class LaborCategory extends Model
|
|||||||
{
|
{
|
||||||
parent::boot();
|
parent::boot();
|
||||||
|
|
||||||
// When sort_order is changed to a value already occupied by another record,
|
|
||||||
// shift all records at that position and above up by 1 to make room.
|
|
||||||
static::saving(function (self $cat) {
|
static::saving(function (self $cat) {
|
||||||
$new = (int) $cat->sort_order;
|
$new = (int) $cat->sort_order;
|
||||||
$old = (int) ($cat->getOriginal('sort_order') ?? PHP_INT_MAX);
|
$old = (int) ($cat->getOriginal('sort_order') ?? PHP_INT_MAX);
|
||||||
|
|
||||||
if ($new === $old) return;
|
if ($new === $old) return;
|
||||||
|
|
||||||
$conflict = static::withoutGlobalScope(TenantScope::class)
|
// Make room: shift all records at >= new position up by 1.
|
||||||
->where('company_id', $cat->company_id)
|
|
||||||
->where('sort_order', $new)
|
|
||||||
->where('id', '!=', $cat->id ?? 0)
|
|
||||||
->exists();
|
|
||||||
|
|
||||||
if ($conflict) {
|
|
||||||
static::withoutGlobalScope(TenantScope::class)
|
static::withoutGlobalScope(TenantScope::class)
|
||||||
->where('company_id', $cat->company_id)
|
->where('company_id', $cat->company_id)
|
||||||
->where('sort_order', '>=', $new)
|
->where('sort_order', '>=', $new)
|
||||||
->where('id', '!=', $cat->id ?? 0)
|
->where('id', '!=', $cat->id ?? 0)
|
||||||
->increment('sort_order', 10);
|
->increment('sort_order');
|
||||||
|
});
|
||||||
|
|
||||||
|
static::saved(function (self $cat) {
|
||||||
|
// Renormalize to 1, 2, 3, … to close any gaps left after the move.
|
||||||
|
$ids = static::withoutGlobalScope(TenantScope::class)
|
||||||
|
->where('company_id', $cat->company_id)
|
||||||
|
->orderBy('sort_order')
|
||||||
|
->orderBy('id')
|
||||||
|
->pluck('id');
|
||||||
|
|
||||||
|
foreach ($ids as $i => $id) {
|
||||||
|
DB::table('labor_categories')
|
||||||
|
->where('id', $id)
|
||||||
|
->update(['sort_order' => $i + 1]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ return new class extends Migration
|
|||||||
foreach ($rows as $i => $id) {
|
foreach ($rows as $i => $id) {
|
||||||
DB::table('labor_categories')
|
DB::table('labor_categories')
|
||||||
->where('id', $id)
|
->where('id', $id)
|
||||||
->update(['sort_order' => ($i + 1) * 10]);
|
->update(['sort_order' => $i + 1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user