refactor(errors): centralise legacy string error codes in ErrorCodes (M21)

~27 ad-hoc error codes (SLOT_TAKEN, USER_NOT_FOUND, VALIDATION, …) were raw
strings, so ErrorCodes::message() returned the "unknown" fallback for them.
Register all 14 distinct codes as constants with their messages and replace the
raw usages across AdminApiController, MyAppointmentsController, CategoryController,
PreRegistrationController and ClinicInvitationController.

Wire values are kept identical (verified no consumer — admin SPA, nobat724_front,
tauri — switches on these strings), so this is backward compatible.

Regression: tests/Shared/ErrorCodesTest (wire values preserved + message resolves).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
hamed
2026-06-28 21:12:23 +03:30
co-authored by Claude Opus 4.8
parent 96a86dbfed
commit 4b80616a17
8 changed files with 102 additions and 29 deletions
+31
View File
@@ -83,6 +83,23 @@ class ErrorCodes
public const ERR_IBAN_LIMIT = 'ERR_IDENTITY_003';
public const ERR_NATIONAL_CODE_UNVERIFIED = 'ERR_IDENTITY_004';
// Legacy domain string codes — centralised here so message() resolves them.
// Wire values are kept identical (e.g. 'SLOT_TAKEN') for client compatibility.
public const VALIDATION = 'VALIDATION';
public const FORBIDDEN = 'FORBIDDEN';
public const NOT_FOUND = 'NOT_FOUND';
public const USER_NOT_FOUND = 'USER_NOT_FOUND';
public const DOCTOR_NOT_FOUND = 'DOCTOR_NOT_FOUND';
public const DOCTOR_EXISTS = 'DOCTOR_EXISTS';
public const CLINIC_NOT_FOUND = 'CLINIC_NOT_FOUND';
public const SLOT_TAKEN = 'SLOT_TAKEN';
public const SLOT_PAST = 'SLOT_PAST';
public const INVALID_ROLE = 'INVALID_ROLE';
public const DUPLICATE_REQUEST = 'DUPLICATE_REQUEST';
public const ERR_GONE = 'ERR_GONE';
public const ERR_MOVED = 'ERR_MOVED';
public const ERR_ACCESS_DENIED = 'ERR_ACCESS_DENIED';
public static function message(string $code): string
{
return match ($code) {
@@ -127,6 +144,20 @@ class ErrorCodes
self::ERR_IBAN_MISMATCH => 'شماره شبا متعلق به شما نیست',
self::ERR_IBAN_LIMIT => 'حداکثر دو شماره شبا می‌توانید ثبت کنید',
self::ERR_NATIONAL_CODE_UNVERIFIED => 'ابتدا کد ملی خود را تأیید کنید',
self::VALIDATION => 'ورودی نامعتبر است',
self::FORBIDDEN => 'دسترسی مجاز نیست',
self::NOT_FOUND => 'منبع یافت نشد',
self::USER_NOT_FOUND => 'کاربر یافت نشد',
self::DOCTOR_NOT_FOUND => 'پزشک یافت نشد',
self::DOCTOR_EXISTS => 'این پزشک قبلاً ثبت شده است',
self::CLINIC_NOT_FOUND => 'کلینیک یافت نشد',
self::SLOT_TAKEN => 'این نوبت قبلاً رزرو شده است',
self::SLOT_PAST => 'زمان این اسلات گذشته است',
self::INVALID_ROLE => 'نقش نامعتبر است',
self::DUPLICATE_REQUEST => 'درخواست تکراری است',
self::ERR_GONE => 'این منبع دیگر در دسترس نیست',
self::ERR_MOVED => 'این منبع منتقل شده است',
self::ERR_ACCESS_DENIED => 'دسترسی مجاز نیست',
default => 'خطای ناشناخته',
};
}