From 2e960c07a15a16b2de4a83bcecc876c067e602d4 Mon Sep 17 00:00:00 2001 From: adonis Date: Wed, 19 Aug 2026 22:02:10 +0330 Subject: [PATCH] fix(settings): keep local can_edit=0 keys in get_settings when SA omits them Customer /api/get_settings dropped price_provider because SuperAdmin catalog did not return it. Merge SA values when present; otherwise keep the tenant copy so the app still receives the key. Co-authored-by: Cursor --- .../Controllers/Admin/SettingsController.php | 60 +++++++++++++++---- .../SuperAdminProgramSettingsOverlay.php | 43 ++++++++++--- 2 files changed, 84 insertions(+), 19 deletions(-) diff --git a/app/Http/Controllers/Admin/SettingsController.php b/app/Http/Controllers/Admin/SettingsController.php index 507b11f..c490692 100644 --- a/app/Http/Controllers/Admin/SettingsController.php +++ b/app/Http/Controllers/Admin/SettingsController.php @@ -162,7 +162,7 @@ class SettingsController extends Controller private function composeSystemSettings($localRows) { $overlay = app(SuperAdminProgramSettingsOverlay::class); - $saMap = $overlay->map(); + $saMap = $overlay->catalogMap(); $byKey = []; @@ -177,7 +177,25 @@ class SettingsController extends Controller ) { continue; } - $byKey[(string) $key] = $this->overlayRowToSetting($item); + $value = $item['value'] ?? null; + if ($value !== null && $value !== '') { + $byKey[(string) $key] = $this->overlayRowToSetting($item); + } + } + foreach ($localRows as $row) { + $key = (string) $row->key; + if (isset($byKey[$key])) { + continue; + } + if ( + SuperAdminProgramSettingsOverlay::isRuntime($key) + || SuperAdminProgramSettingsOverlay::isLocalOwned($key) + ) { + continue; + } + if (! $this->isEditableCanEdit($row->can_edit ?? null)) { + $byKey[$key] = $row; + } } } else { foreach ($localRows as $row) { @@ -219,14 +237,15 @@ class SettingsController extends Controller } /** - * get_settings: کلیدهای سوپرادمین (can_edit=0) + ردیف‌های جدول لوکال با can_edit=1. + * get_settings اپ/ادمین: + * can_edit=1 (+ runtime) از DB لوکال + * can_edit=0 از سوپرادمین؛ اگر کلید در SA نبود یا value خالی بود → کپی لوکال * اگر سوپرادمین در دسترس نباشد کل جدول لوکال برمی‌گردد. - * کلیدهای runtime / متعلق به پنل خانگی همیشه از جدول لوکال می‌آیند. */ private function composeGetSettings($localRows) { $overlay = app(SuperAdminProgramSettingsOverlay::class); - $saMap = $overlay->map(); + $saMap = $overlay->catalogMap(); if ($saMap === null) { return $localRows; } @@ -234,8 +253,13 @@ class SettingsController extends Controller $byKey = []; foreach ($localRows as $row) { - if ($this->isEditableCanEdit($row->can_edit ?? null)) { - $byKey[(string) $row->key] = $this->normalizeTenantOwnedRow($row); + $key = (string) $row->key; + if ( + $this->isEditableCanEdit($row->can_edit ?? null) + || SuperAdminProgramSettingsOverlay::isRuntime($key) + || SuperAdminProgramSettingsOverlay::isLocalOwned($key) + ) { + $byKey[$key] = $this->normalizeTenantOwnedRow($row); } } @@ -243,22 +267,34 @@ class SettingsController extends Controller if (! is_array($item)) { continue; } + $key = (string) $key; if ( - SuperAdminProgramSettingsOverlay::isRuntime((string) $key) - || SuperAdminProgramSettingsOverlay::isLocalOwned((string) $key) + SuperAdminProgramSettingsOverlay::isRuntime($key) + || SuperAdminProgramSettingsOverlay::isLocalOwned($key) ) { continue; } - $byKey[(string) $key] = $this->overlayRowToSetting($item); + $value = $item['value'] ?? null; + if ($value !== null && $value !== '') { + $byKey[$key] = $this->overlayRowToSetting($item); + } } foreach ($localRows as $row) { $key = (string) $row->key; + if (isset($byKey[$key])) { + continue; + } if ( - SuperAdminProgramSettingsOverlay::isLocalOwned($key) - || SuperAdminProgramSettingsOverlay::isRuntime($key) + SuperAdminProgramSettingsOverlay::isRuntime($key) + || SuperAdminProgramSettingsOverlay::isLocalOwned($key) ) { $byKey[$key] = $this->normalizeTenantOwnedRow($row); + + continue; + } + if (! $this->isEditableCanEdit($row->can_edit ?? null)) { + $byKey[$key] = $row; } } diff --git a/app/Services/SuperAdminProgramSettingsOverlay.php b/app/Services/SuperAdminProgramSettingsOverlay.php index 6ee727e..cc45f99 100644 --- a/app/Services/SuperAdminProgramSettingsOverlay.php +++ b/app/Services/SuperAdminProgramSettingsOverlay.php @@ -3,7 +3,7 @@ namespace App\Services; /** - * تنظیمات پیشرفته سوپرادمین برای ConfigService. + * تنظیمات پیشرفته سوپرادمین برای ConfigService و get_settings. * کش پایدار ندارد؛ فقط یک بار در همان درخواست PHP نگه داشته می‌شود. */ class SuperAdminProgramSettingsOverlay @@ -36,9 +36,43 @@ class SuperAdminProgramSettingsOverlay private static bool $loaded = false; /** - * @return array>|null null = سوپرادمین در دسترس نبود + * همهٔ کلیدهای سوپرادمین (حتی value خالی). null = سوپرادمین در دسترس نبود. + * + * @return array>|null + */ + public function catalogMap(): ?array + { + return $this->load(); + } + + /** + * فقط کلیدهایی که سوپرادمین مقدار غیرخالی دارد — برای ConfigService. + * + * @return array>|null */ public function map(): ?array + { + $full = $this->load(); + if ($full === null) { + return null; + } + + $withValue = []; + foreach ($full as $key => $row) { + $value = is_array($row) ? ($row['value'] ?? null) : null; + if ($value === null || $value === '') { + continue; + } + $withValue[$key] = $row; + } + + return $withValue; + } + + /** + * @return array>|null + */ + private function load(): ?array { if (self::$loaded) { return self::$memo; @@ -62,11 +96,6 @@ class SuperAdminProgramSettingsOverlay if ($key === '' || in_array($key, self::LOCAL_OWNED_KEYS, true) || in_array($key, self::RUNTIME_KEYS, true)) { continue; } - // مقدار خالی قالب سوپرادمین نباید value لوکال tenant را پاک کند - $value = $row['value'] ?? null; - if ($value === null || $value === '') { - continue; - } $map[$key] = $row; }