Files
autocrm/app/Models/Tenant/LaborCategory.php
T
Vasyka 5610282078 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>
2026-09-08 06:59:14 +00:00

69 lines
2.2 KiB
PHP

<?php
namespace App\Models\Tenant;
use App\Models\Concerns\BelongsToTenant;
use App\Models\Scopes\TenantScope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
class LaborCategory extends Model
{
use BelongsToTenant;
protected $fillable = ['company_id', 'name', 'name_ro', 'name_ru', 'name_en', 'sort_order'];
protected static function boot(): void
{
parent::boot();
static::saving(function (self $cat) {
$new = (int) $cat->sort_order;
$old = (int) ($cat->getOriginal('sort_order') ?? PHP_INT_MAX);
if ($new === $old) return;
// Make room: shift all records at >= new position up by 1.
static::withoutGlobalScope(TenantScope::class)
->where('company_id', $cat->company_id)
->where('sort_order', '>=', $new)
->where('id', '!=', $cat->id ?? 0)
->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]);
}
});
}
protected $casts = ['sort_order' => 'integer'];
/** Localized display label — falls back through ru→en→name_ro→name. */
public function label(?string $locale = null): string
{
$locale = $locale ?: app()->getLocale();
return $this->{"name_{$locale}"}
?: $this->name_ro
?: $this->name
?: '';
}
/** Options array keyed by canonical name (stored in labors.category). */
public static function optionsForSelect(): array
{
return static::orderBy('sort_order')->orderBy('name')->get()
->mapWithKeys(fn ($c) => [$c->name => $c->label()])
->toArray();
}
}