diff --git a/prisma/setting-templates-from-deploy.json b/prisma/setting-templates-from-deploy.json index d60c3f6..22a741e 100644 --- a/prisma/setting-templates-from-deploy.json +++ b/prisma/setting-templates-from-deploy.json @@ -5,7 +5,7 @@ "title_fa": "سیستم حسابداری", "can_edit": 0, "is_active": 1, - "description": "none,pargar,tahesab,zarin", + "description": "سیستم حسابداری: none=هیچکدام، pargar=API پرگار، tahesab=ارسال خودکار ته‌حساب، zarin=ارسال خودکار زرین.", "type": "" }, { @@ -14,7 +14,7 @@ "title_fa": "آدرس پنل ادمین", "can_edit": 0, "is_active": 1, - "description": "", + "description": "آدرس کامل پنل مدیریت (با https). برای لینک‌های ادمین و تنظیمات CORS در صورت نیاز.", "type": "text" }, { @@ -32,7 +32,7 @@ "title_fa": "آدرس اپ (کاربر)", "can_edit": 0, "is_active": 1, - "description": "", + "description": "آدرس کامل وب‌اپ کاربر (با https). در لینک‌های پیامک، بازگشت از درگاه و ارجاعات داخلی استفاده می‌شود.", "type": "text" }, { @@ -41,7 +41,7 @@ "title_fa": "توکن بات بله", "can_edit": 0, "is_active": 1, - "description": "", + "description": "توکن ربات بله برای ارسال اعلان‌ها. محرمانه.", "type": "text" }, { @@ -50,7 +50,7 @@ "title_fa": "UUID نمودار Zaarbox", "can_edit": 0, "is_active": 1, - "description": "خالی = UUID پیش‌فرض سرویس", + "description": "شناسه یکتا (UUID) نمودار در سرویس تابلو. اگر خالی باشد از شناسه پیش‌فرض سرویس استفاده می‌شود.", "type": "text" }, { @@ -59,7 +59,7 @@ "title_fa": "نمودار از داده خود سایت", "can_edit": 0, "is_active": 1, - "description": "خاموش = Zaarbox (chart_id) | روشن = تاریخچه ذخیره‌شده prices", + "description": "روشن: نمودار قیمت از تاریخچه ذخیره‌شده در دیتابیس خودتان. خاموش: از سرویس تابلو آنلاین (با شناسه chart_id) استفاده می‌شود.", "type": "switch" }, { @@ -122,7 +122,7 @@ "title_fa": "پیامک تکی به مشتری از لیست", "can_edit": 0, "is_active": 1, - "description": "روشن: در لیست مشتریان دکمه ارسال پیامک تکی نمایش داده می‌شود. خاموش: مخفی است. فقط از صفحه دیپلوی قابل تغییر است.", + "description": "روشن: در لیست مشتریان دکمه ارسال پیامک تکی نمایش داده می‌شود و ادمین می‌تواند برای هر مشتری متن دلخواه بفرستد. خاموش: دکمه مخفی است. فقط از صفحه دیپلوی تغییر می‌کند.", "type": "switch" }, { @@ -167,7 +167,7 @@ "title_fa": "فعال‌سازی API سفارش خارجی (get_wallet / order)", "can_edit": 0, "is_active": 1, - "description": "true + node_client_id + node_shared_secret", + "description": "روشن: API دریافت کیف پول و ثبت سفارش از سرویس فروشگاه خارجی فعال است. نیاز به node_client_id و node_shared_secret دارد.", "type": "switch" }, { @@ -257,7 +257,7 @@ "title_fa": "صفحه کسب درآمد", "can_edit": 0, "is_active": 1, - "description": "", + "description": "روشن: منوی «کسب درآمد / دعوت دوستان» در اپ کاربر نمایش داده می‌شود.", "type": "switch" }, { @@ -293,7 +293,7 @@ "title_fa": "حالت فروشگاهی", "can_edit": 0, "is_active": 1, - "description": "فعال = سبد خرید، دسته‌بندی، حواله، تخفیف", + "description": "نوع چیدمان اپ: روشن = حالت فروشگاهی (سبد، دسته‌بندی، حواله و …). خاموش = حالت معامله آبشده/محصولات کلاسیک. فقط از دیپلوی تغییر می‌کند.", "type": "switch" }, { @@ -311,7 +311,7 @@ "title_fa": "لوگوی صفحه ورود", "can_edit": 0, "is_active": 0, - "description": "", + "description": "آدرس تصویر لوگو در صفحه ورود. معمولاً از طریق دیپلوی یا آپلود فایل تنظیم می‌شود؛ در پنل قابل ویرایش نیست.", "type": "text" }, { @@ -320,7 +320,7 @@ "title_fa": "لوگوی ثبت‌نام", "can_edit": 0, "is_active": 0, - "description": "", + "description": "آدرس تصویر لوگو در صفحه ثبت‌نام. معمولاً از طریق دیپلوی تنظیم می‌شود؛ در پنل قابل ویرایش نیست.", "type": "text" }, { @@ -332,9 +332,18 @@ "description": "", "type": "text" }, + { + "key": "main_product", + "value": "", + "title_fa": "محصول آبشده", + "can_edit": 0, + "is_active": 1, + "description": "شناسه عددی یا نام reading_method محصول آبشده مرجع. وقتی منبع قیمت روی main_product باشد برای محاسبه استفاده می‌شود.", + "type": "text" + }, { "key": "main_wallet_products", - "value": "13", + "value": "", "title_fa": "محصولات متصل به کیف اصلی", "can_edit": 0, "is_active": 1, @@ -347,7 +356,7 @@ "title_fa": "عنوان فلز در UI", "can_edit": 0, "is_active": 1, - "description": "", + "description": "عنوان فلز اصلی در رابط کاربر (مثلاً «طلای آبشده» یا «کاتد مس»). در دارایی، کیف پول و برچسب‌های معامله دیده می‌شود. فقط از دیپلوی/SQL تغییر می‌کند.", "type": "text" }, { @@ -356,7 +365,7 @@ "title_fa": "نام فروشگاه در درگاه", "can_edit": 0, "is_active": 1, - "description": "", + "description": "نام فروشگاه که در درگاه پرداخت و رسید بانکی به کاربر نمایش داده می‌شود.", "type": "text" }, { @@ -365,7 +374,7 @@ "title_fa": "آدرس سرور همکار", "can_edit": 0, "is_active": 1, - "description": "", + "description": "آدرس پایه سرور API همکار (بدون اسلش انتهایی). مثال: https://example.com", "type": "text" }, { @@ -374,7 +383,7 @@ "title_fa": "شناسه کلاینت API خارجی (X-Client-Id)", "can_edit": 0, "is_active": 1, - "description": "", + "description": "شناسه کلاینت برای API سفارش خارجی (هدر X-Client-Id). باید با مقدار تنظیم‌شده در سرویس مقصد یکسان باشد.", "type": "text" }, { @@ -383,7 +392,7 @@ "title_fa": "کلید امضای HMAC API خارجی", "can_edit": 0, "is_active": 1, - "description": "", + "description": "کلید مشترک امضای HMAC برای احراز درخواست‌های API سفارش خارجی. محرمانه نگه دارید.", "type": "text" }, { @@ -397,7 +406,7 @@ }, { "key": "pargar_item_id_gold", - "value": "11", + "value": "", "title_fa": "کد کالای طلا پرگار", "can_edit": 0, "is_active": 1, @@ -406,7 +415,7 @@ }, { "key": "pargar_item_id_rial", - "value": "0", + "value": "", "title_fa": "کد کالای ریال پرگار", "can_edit": 0, "is_active": 1, @@ -433,11 +442,11 @@ }, { "key": "payping_fin_customer_id", - "value": "23", + "value": "", "title_fa": "customer_id fin", "can_edit": 0, "is_active": 1, - "description": "", + "description": "شناسه مشتری/حساب در سامانه fin که تراکنش‌ها به نام آن ثبت می‌شوند.", "type": "number" }, { @@ -446,7 +455,7 @@ "title_fa": "همگام‌سازی fin", "can_edit": 0, "is_active": 1, - "description": "", + "description": "روشن: پس از واریز/برداشت، تراکنش به سامانه حسابداری fin همگام‌سازی می‌شود.", "type": "switch" }, { @@ -455,16 +464,16 @@ "title_fa": "توکن fin", "can_edit": 0, "is_active": 1, - "description": "", + "description": "توکن احراز هویت برای API سامانه fin.", "type": "text" }, { "key": "payping_fin_url", - "value": "https://limangold.ir/kernel/admin/fin", + "value": "", "title_fa": "URL fin", "can_edit": 0, "is_active": 1, - "description": "", + "description": "آدرس کامل endpoint ثبت تراکنش در سامانه fin (POST).", "type": "text" }, { @@ -473,7 +482,7 @@ "title_fa": "لیست item (چرخشی)", "can_edit": 0, "is_active": 1, - "description": "", + "description": "لیست کدهای item درگاه (با کاما) برای چرخش بین چند merchant.", "type": "text" }, { @@ -482,7 +491,7 @@ "title_fa": "نام gateway درگاه", "can_edit": 0, "is_active": 1, - "description": "sepal,", + "description": "نام درگاه پرداخت فعال که به سرویس واسط درگاه ارسال می‌شود|sepal,", "type": "select" }, { @@ -491,34 +500,34 @@ "title_fa": "گرد کردن مبلغ به تومان", "can_edit": 0, "is_active": 1, - "description": "", + "description": "روشن: مبلغ پرداخت به نزدیک‌ترین تومان گرد می‌شود. خاموش: مبلغ دقیق ریالی.", "type": "switch" }, { "key": "payping_start_url", - "value": "https://payping.limangold.ir/payment/start", + "value": "", "title_fa": "آدرس شروع درگاه", "can_edit": 0, "is_active": 1, - "description": "", + "description": "آدرس API شروع پرداخت (redirect کاربر به درگاه).", "type": "text" }, { "key": "payping_strict_failed_withdraw", "value": "false", - "title_fa": "اولویت تراکنش ناموفق", + "title_fa": "برداشت ناموفق سخت‌گیرانه", "can_edit": 0, "is_active": 1, - "description": "", + "description": "روشن: در صورت وجود برداشت ناموفق قبلی، تسویه جدید با احتیاط بیشتر انجام می‌شود.", "type": "switch" }, { "key": "payping_verify_url", - "value": "https://payping.limangold.ir/payment/verify", + "value": "", "title_fa": "آدرس تأیید درگاه", "can_edit": 0, "is_active": 1, - "description": "", + "description": "آدرس API تأیید و نهایی‌سازی پرداخت پس از بازگشت از درگاه.", "type": "text" }, { @@ -566,13 +575,31 @@ "description": "آیدی چنل/گروه تلگرام برای ارسال قیمت (چند مقصد با ویرگول).", "type": "text" }, + { + "key": "price_provider", + "value": "", + "title_fa": "منبع قیمت", + "can_edit": 0, + "is_active": 1, + "description": "منبع دریافت قیمت لحظه‌ای برای اپ کاربر و همگام‌سازی محصولات. مقدار montzar = قیمت از همکار (Montzar).|montzar,zaarbox,main_product", + "type": "select" + }, + { + "key": "profit_gold_api_enabled", + "value": "false", + "title_fa": "API سود طلا", + "can_edit": 0, + "is_active": 0, + "description": "روشن: API محاسبه سود طلا فعال است. در اکثر نصب‌ها خاموش می‌ماند.", + "type": "switch" + }, { "key": "referral_bonus_amount", "value": "", "title_fa": "مقدار پاداش معرف", "can_edit": 0, "is_active": 1, - "description": "", + "description": "مبلغ یا مقدار پاداش معرف (متن آزاد — بسته به پیاده‌سازی پیامک/اعتبار). برای نمایش در پیام‌ها.", "type": "text" }, { @@ -596,10 +623,10 @@ { "key": "send_to_tahesab", "value": "false", - "title_fa": "ارسال به ته‌حساب (قدیمی)", + "title_fa": "ارسال به ته‌حساب", "can_edit": 0, "is_active": 0, - "description": "", + "description": "روشن: واریز و برداشت مشتریان به‌صورت خودکار به ته‌حساب ارسال می‌شود.", "type": "" }, { @@ -626,7 +653,7 @@ "title_fa": "مسیر SSE قیمت", "can_edit": 0, "is_active": 1, - "description": "GET لاراول — استریم event:last و event:list با payload کامل", + "description": "مسیر GET لاراول برای استریم قیمت — پیش‌فرض /api/price/stream", "type": "text" }, { @@ -635,16 +662,16 @@ "title_fa": "حساب بانکی ته‌حساب", "can_edit": 0, "is_active": 1, - "description": "", + "description": "نام یا کد حساب بانکی در سند واریز/برداشت ته‌حساب.", "type": "text" }, { "key": "tahesab_db", "value": "", - "title_fa": "دیتابیس ته‌حساب", + "title_fa": "نام دیتابیس ته‌حساب", "can_edit": 0, "is_active": 1, - "description": "", + "description": "نام دیتابیس یا شناسه پایگاه در ته‌حساب که سند به آن ارسال می‌شود.", "type": "text" }, { @@ -653,7 +680,7 @@ "title_fa": "آدرس IP سرور ته‌حساب", "can_edit": 0, "is_active": 1, - "description": "", + "description": "آدرس IP یا hostname سرور نرم‌افزار ته‌حساب روی شبکه داخلی.", "type": "text" }, { @@ -662,7 +689,7 @@ "title_fa": "پورت سرور ته‌حساب", "can_edit": 0, "is_active": 1, - "description": "", + "description": "شماره پورت اتصال به API ته‌حساب (معمولاً 8080 یا مقدار مستندات ته‌حساب).", "type": "number" }, { @@ -671,7 +698,7 @@ "title_fa": "توکن ته‌حساب", "can_edit": 0, "is_active": 1, - "description": "", + "description": "توکن/API Key اتصال به ته‌حساب. از پنل ته‌حساب دریافت می‌شود.", "type": "text" }, { @@ -680,7 +707,25 @@ "title_fa": "توکن بات تلگرام", "can_edit": 0, "is_active": 1, - "description": "", + "description": "توکن ربات تلگرام برای ارسال اعلان‌ها. از BotFather دریافت می‌شود. محرمانه.", + "type": "text" + }, + { + "key": "title_fav", + "value": "", + "title_fa": "عنوان favicon", + "can_edit": 0, + "is_active": 0, + "description": "عنوان نمایش‌داده‌شده در تب مرورگر (favicon). از دیپلوی مدیریت می‌شود.", + "type": "text" + }, + { + "key": "title_pwa", + "value": "", + "title_fa": "عنوان PWA", + "can_edit": 0, + "is_active": 0, + "description": "عنوان کوتاه برای نصب PWA روی موبایل. از دیپلوی مدیریت می‌شود.", "type": "text" }, { @@ -689,7 +734,7 @@ "title_fa": "واحد وزن دارایی و معاملات", "can_edit": 0, "is_active": 1, - "description": "واحد نمایش وزن فلز در دارایی‌ها، کیف پول و تراکنش‌ها|گرم,کیلوگرم", + "description": "واحد نمایش وزن در دارایی‌ها، کیف پول و جزئیات معاملات|گرم,کیلوگرم", "type": "select" }, { @@ -707,9 +752,18 @@ "title_fa": "قیمت لحظه‌ای (SSE)", "can_edit": 0, "is_active": 1, - "description": "روشن: اپ به sse_path وصل می‌شود؛ خاموش: polling /api/price/last و /customer/product/list", + "description": "روشن: اپ به SSE (sse_path) وصل می‌شود و last/list با payload می‌آید؛ خاموش: polling.", "type": "switch" }, + { + "key": "zaarbox_api_url", + "value": "", + "title_fa": "آدرس API تابلو Zaarbox", + "can_edit": 0, + "is_active": 1, + "description": "آدرس سرور(های) فید قیمت (/api/free). تا ۵ آدرس (JSON آرایه) پشتیبانی می‌شود؛ اگر آدرس اول پاسخ ندهد به‌ترتیب سراغ بعدی می‌رود. مقدار تکی قبلی حفظ می‌شود.", + "type": "text" + }, { "key": "zarin_api", "value": "", @@ -721,7 +775,7 @@ }, { "key": "zarin_gorohe_kar", - "value": "52", + "value": "", "title_fa": "گروه کار پیش‌فرض زرین", "can_edit": 0, "is_active": 1, @@ -730,7 +784,7 @@ }, { "key": "zarin_name_g", - "value": "مشتری نقدی (خریدار)", + "value": "", "title_fa": "نام گروه حساب مشتریان زرین", "can_edit": 0, "is_active": 1, @@ -739,7 +793,7 @@ }, { "key": "zarin_noe_kar", - "value": "16", + "value": "", "title_fa": "نوع کار پیش‌فرض زرین", "can_edit": 0, "is_active": 1, @@ -748,7 +802,7 @@ }, { "key": "zarin_noe_kar_tedadi", - "value": "17", + "value": "", "title_fa": "نوع کار تعدادی زرین", "can_edit": 0, "is_active": 1, diff --git a/scripts/sync-superadmin-setting-template.mjs b/scripts/sync-superadmin-setting-template.mjs index 219703c..3b89bdb 100644 --- a/scripts/sync-superadmin-setting-template.mjs +++ b/scripts/sync-superadmin-setting-template.mjs @@ -5,6 +5,8 @@ * - prisma/setting-templates-from-deploy.json (فقط can_edit=0 نهایی) * - src/program-settings/deploy-setting-catalog-keys.ts * - ../controlpanel_user/src/config/superAdminSettingKeys.ts + * + * قالب value خالی است برای توکن/رمز/شناسه پروژه — هر پروژه در سوپرادمین مقدار خودش را دارد. */ import { readFileSync, writeFileSync } from 'fs'; import { dirname, join } from 'path'; @@ -31,30 +33,103 @@ function unquote(s) { .replace(/\\n/g, '\n'); } -// INSERT … SELECT 'key', 'value', … -for (const m of sql.matchAll( - /SELECT\s+'([^']+)',\s+'((?:\\'|[^'])*)',\s+'((?:\\'|[^'])*)',\s+(\d+),\s+(\d+)(?:,\s+(NULL|'(?:\\'|[^'])*'))(?:,\s+'((?:\\'|[^'])*)')?/g, -)) { - const key = m[1]; - const value = unquote(`'${m[2]}'`); - const title_fa = unquote(`'${m[3]}'`); - const can_edit = Number(m[4]); - const is_active = Number(m[5]); - let description = ''; - if (m[6] && m[6] !== 'NULL') description = unquote(m[6]); - const type = m[7] ? unquote(`'${m[7]}'`) : ''; - rows.set(key, { key, value, title_fa, can_edit, is_active, description, type }); +function parseSqlList(expr) { + const out = []; + let i = 0; + const s = String(expr ?? '').trim(); + while (i < s.length) { + while (i < s.length && /[\s,]/.test(s[i])) i += 1; + if (i >= s.length) break; + if (s[i] === "'") { + i += 1; + let buf = ''; + while (i < s.length) { + if (s[i] === '\\' && i + 1 < s.length) { + buf += s[i + 1]; + i += 2; + continue; + } + if (s[i] === "'") { + if (s[i + 1] === "'") { + buf += "'"; + i += 2; + continue; + } + i += 1; + break; + } + buf += s[i]; + i += 1; + } + out.push(buf); + continue; + } + let buf = ''; + while (i < s.length && s[i] !== ',') { + buf += s[i]; + i += 1; + } + out.push(buf.trim()); + } + return out; +} + +function ensureRow(key) { + const k = String(key || '').trim(); + if (!k) return null; + let row = rows.get(k); + if (!row) { + row = { + key: k, + value: '', + title_fa: k, + can_edit: 0, + is_active: 1, + description: '', + type: '', + }; + rows.set(k, row); + } + return row; } function applyCanEdit(block, value) { const keys = [...block.matchAll(/'([^']+)'/g)].map((x) => x[1]); for (const key of keys) { - const row = rows.get(key); + const row = ensureRow(key); if (row) row.can_edit = value; } } -// UPDATE can_edit = 0/1 batches +function isBlankSql(v) { + const t = String(v ?? '').trim(); + return t === '' || t === 'NULL' || t.startsWith('@'); +} + +// INSERT INTO settings (cols) SELECT ... +for (const m of sql.matchAll( + /INSERT INTO `settings` \(([^)]+)\)\s*SELECT\s+([\s\S]*?)\nWHERE NOT EXISTS/g, +)) { + const cols = m[1].split(',').map((c) => c.replace(/[`\s]/g, '')); + const values = parseSqlList(m[2]); + const rec = {}; + cols.forEach((col, i) => { + rec[col] = values[i]; + }); + const key = rec.key; + if (!key || isBlankSql(key)) continue; + const row = ensureRow(key); + if (!isBlankSql(rec.value) && rec.value !== undefined) row.value = unquote(rec.value); + if (!isBlankSql(rec.title_fa) && rec.title_fa !== undefined) row.title_fa = unquote(rec.title_fa); + if (rec.can_edit !== undefined && !isBlankSql(rec.can_edit)) row.can_edit = Number(rec.can_edit); + if (rec.is_active !== undefined && !isBlankSql(rec.is_active)) row.is_active = Number(rec.is_active); + if (!isBlankSql(rec.description) && rec.description !== undefined) { + row.description = unquote(rec.description); + } + if (!isBlankSql(rec.type) && rec.type !== undefined) row.type = unquote(rec.type); +} + +// UPDATE can_edit = 0/1 batches (بعد از INSERT — منبع حقیقت نهایی) for (const m of sql.matchAll( /UPDATE\s+`settings`\s+SET\s+`can_edit`\s*=\s*(\d)(?:,\s*`[^`]+`\s*=[^W]+)?\s+WHERE\s+`key`\s+IN\s*\(([\s\S]*?)\)\s*;/g, )) { @@ -64,18 +139,16 @@ for (const m of sql.matchAll( for (const m of sql.matchAll( /UPDATE\s+`settings`\s+SET\s+`can_edit`\s*=\s*(\d)\s+WHERE\s+`key`\s*=\s*'([^']+)'/g, )) { - const row = rows.get(m[2]); + const row = ensureRow(m[2]); if (row) row.can_edit = Number(m[1]); } -// zarin_* wildcard if (/UPDATE\s+`settings`\s+SET\s+`can_edit`\s*=\s*0,\s*`is_active`\s*=\s*1\s+WHERE\s+`key`\s+LIKE\s+'zarin_%'/.test(sql)) { for (const [key, row] of rows) { if (key.startsWith('zarin_')) row.can_edit = 0; } } -// type-only UPDATE batches — enrich type when present for (const m of sql.matchAll( /UPDATE\s+`settings`\s+SET\s+`type`\s*=\s*'([^']+)'\s+WHERE\s+`key`\s+IN\s*\(([\s\S]*?)\)\s*;/g, )) { @@ -86,6 +159,51 @@ for (const m of sql.matchAll( } } +for (const m of sql.matchAll( + /UPDATE\s+`settings`\s+SET\s+`title_fa`\s*=\s+'((?:\\'|[^'])*)'\s+WHERE\s+`key`\s*=\s*'([^']+)'/g, +)) { + const row = rows.get(m[2]); + if (row && m[1]) row.title_fa = unquote(`'${m[1]}'`); +} + +for (const m of sql.matchAll( + /UPDATE\s+`settings`\s+SET\s+`description`\s*=\s+'((?:\\'|[^'])*)'\s+WHERE\s+`key`\s*=\s*'([^']+)'/g, +)) { + const row = rows.get(m[2]); + if (row && m[1]) row.description = unquote(`'${m[1]}'`); +} + +const SECRET_OR_PROJECT_VALUE = /(token|password|secret|api_key|sheba|card_number|client_secret|client_id|username)$/i; +const EMPTY_TEMPLATE_VALUE_KEYS = new Set([ + 'main_product', + 'main_wallet_products', + 'payping_fin_customer_id', + 'payping_fin_url', + 'payping_start_url', + 'payping_verify_url', + 'price_provider', + 'pargar_item_id_gold', + 'pargar_item_id_rial', + 'zarin_noe_kar', + 'zarin_noe_kar_tedadi', + 'zarin_gorohe_kar', + 'zarin_name_g', +]); + +function templateValue(row) { + const key = row.key; + if (SECRET_OR_PROJECT_VALUE.test(key) || EMPTY_TEMPLATE_VALUE_KEYS.has(key)) return ''; + const v = String(row.value ?? ''); + if (/^eyJ/.test(v) || v.startsWith('http') && /token|secret/i.test(key)) return ''; + return v; +} + +const EXTRA_EDITABLE = ['fee', 'referral_bonus_count']; +for (const key of EXTRA_EDITABLE) { + const row = ensureRow(key); + if (row) row.can_edit = 1; +} + const systemRows = [...rows.values()] .filter((r) => r.can_edit === 0) .sort((a, b) => a.key.localeCompare(b.key)); @@ -96,7 +214,7 @@ const editableRows = [...rows.values()] const jsonOut = systemRows.map((r) => ({ key: r.key, - value: r.value ?? '', + value: templateValue(r), title_fa: r.title_fa ?? r.key, can_edit: 0, is_active: r.is_active ?? 1, @@ -145,3 +263,22 @@ writeFileSync(join(root, '../controlpanel_user/src/config/superAdminSettingKeys. console.log(`system keys (can_edit=0): ${systemRows.length}`); console.log(`editable keys (can_edit=1): ${editableRows.length}`); +const mustHave = [ + 'price_provider', + 'zaarbox_api_url', + 'main_product', + 'profit_gold_api_enabled', + 'title_pwa', + 'title_fav', + 'unit', + 'main_wallet_products', +]; +for (const key of mustHave) { + const ok = systemRows.some((r) => r.key === key); + console.log(` ${ok ? 'OK' : 'MISSING'} ${key}`); +} +const mustNot = ['montzar_token', 'montzar_diff', 'name_fa', 'buy_fee']; +for (const key of mustNot) { + const bad = systemRows.some((r) => r.key === key); + console.log(` ${bad ? 'LEAK' : 'OK'} system must not contain ${key}`); +} diff --git a/src/program-settings/deploy-setting-catalog-keys.ts b/src/program-settings/deploy-setting-catalog-keys.ts index be4cab5..845476e 100644 --- a/src/program-settings/deploy-setting-catalog-keys.ts +++ b/src/program-settings/deploy-setting-catalog-keys.ts @@ -40,6 +40,7 @@ export const DEPLOY_SETTING_CATALOG_KEYS = new Set([ "logo_login", "logo_register", "main_metal", + "main_product", "main_wallet_products", "metal_type", "montify_name", @@ -66,6 +67,8 @@ export const DEPLOY_SETTING_CATALOG_KEYS = new Set([ "price_channel_bale_to", "price_channel_rubika_to", "price_channel_telegram_to", + "price_provider", + "profit_gold_api_enabled", "referral_bonus_amount", "rubika_bot_token", "send_to_pargar", @@ -79,9 +82,12 @@ export const DEPLOY_SETTING_CATALOG_KEYS = new Set([ "tahesab_port", "tahesab_token", "telegram_bot_token", + "title_fav", + "title_pwa", "unit", "wallet_payment_provider", "wss_enabled", + "zaarbox_api_url", "zarin_api", "zarin_gorohe_kar", "zarin_name_g", @@ -109,14 +115,18 @@ export const DEPLOY_SETTING_EDITABLE_KEYS = new Set([ "deposit_method_shetab", "deposit_sheba", "deposit_sms_support_number", + "deposit_support_message_text", + "do_send_liman", "down_price", "endDay", + "fee", "fee_conditional_order", "fee_free", "fee_service_charge_percentage", "gift_for_referral", "gift_for_referrer", "has_chat", + "invite_link_text", "jibit_verification", "main_product_price", "min_deposit", @@ -144,12 +154,14 @@ export const DEPLOY_SETTING_EDITABLE_KEYS = new Set([ "price_channel_footer_id", "price_channel_footer_link", "price_channel_footer_phone", + "price_channel_message_text", "price_channel_messengers", "price_channel_min_seconds", "price_extreme_date", "products_site_link_enabled", "products_site_link_text", "products_site_link_url", + "referral_bonus_count", "referral_gift_buy_from_montzar", "referral_gift_on_first_order", "referral_id", @@ -186,8 +198,12 @@ export const DEPLOY_SETTING_EDITABLE_KEYS = new Set([ "support_messenger", "support_messenger_id", "support_messenger_text", + "support_messengers", + "text_about", + "text_rule", "tracking_systems", "tracking_systems_enabled", "up_price", + "zaarbox_price_key", ]);