fix(customer): use next free id instead of stale AUTO_INCREMENT after manual id edits

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-11-05 11:20:24 +03:30
co-authored by Cursor
parent 9ec71efcbb
commit e65b8053fd
2 changed files with 28 additions and 0 deletions
@@ -3,6 +3,7 @@
فرمت هر خط:
- YYYY-MM-DD | موضوع | مسیر فایل(ها) | نکتهٔ ۱ خطی
- 2026-11-05 | کد کاربری مشتری بعدی | `Customer::nextSequentialId` در `creating` | کد کاربری=`customers.id`؛ بعد از UPDATE دستی id، AUTO_INCREMENT پایین نمی‌آید (۵۵۱ به‌جای ۲۴). ایجاد مشتری = اولین id خالی، نه شمارندهٔ InnoDB
- 2026-11-04 | فرمت کد تفصیلی شایگان | `ShayeganSyncService::customerTafsilNumber` | کل `shayegan_kol_customer` (121) + کد کاربر ۷رقمی: مشتری 1 → `1210000001`. کد ذخیره‌شدهٔ قبلی عوض نمی‌شود
- 2026-11-02 | جدول اسناد شایگان | `shayeganTable.vue` + `ShayeganController::table` | BaseTable؛ پاسخ بدون `query` را خود فرانت به `{rows,query}` برمی‌گرداند. ستون عملیات `ops` است تا در RTL هشدار fixed ندهد
- 2026-11-02 | ویرایش کد حسابداری شایگان | `CustomerAccountingCodeModal.vue` | provider شایگان هم `moshtari_code` ذخیره می‌کند؛ قبلاً فقط پرگار/ته‌حساب/زرین قبول می‌شد و پیام «حسابداری فعال نیست» می‌آمد
+27
View File
@@ -5,6 +5,7 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Carbon\Carbon;
use Rooyesh\Wallet\models\Wallet;
@@ -200,6 +201,16 @@ class Customer extends Authenticatable implements JWTSubject
protected static function booted(): void
{
// کد کاربری = customers.id. AUTO_INCREMENT بعد از UPDATE دستی id پایین نمی‌آید
// (مثلاً ۱..۲۳ اصلاح شد ولی شمارنده روی ۵۵۱ ماند). همیشه اولین id خالی.
static::creating(function (self $customer) {
if (! empty($customer->id)) {
return;
}
$customer->id = self::nextSequentialId();
$customer->incrementing = false;
});
static::saving(function (self $customer) {
$mobile = self::normalizeMobile($customer->mobile);
if ($mobile === null) {
@@ -211,6 +222,22 @@ class Customer extends Authenticatable implements JWTSubject
});
}
/** کوچک‌ترین id آزاد، شامل ردیف‌های soft-deleted تا PK تکراری نشود. */
public static function nextSequentialId(): int
{
$table = (new static)->getTable();
$row = DB::selectOne(
"SELECT t.id + 1 AS next_id
FROM (SELECT 0 AS id UNION ALL SELECT id FROM `{$table}`) t
LEFT JOIN `{$table}` c ON c.id = t.id + 1
WHERE c.id IS NULL
ORDER BY t.id
LIMIT 1"
);
return max(1, (int) ($row->next_id ?? 1));
}
public static function normalizeMobile(?string $mobile): ?string
{
$digits = preg_replace('/\D+/', '', trim((string) $mobile));