# مراحل ساده: مهاجرت SMS و کار موازی هدف: اول داده واقعی همکار/خانگی برود داخل سوپرادمین، بعد هر دو پنل با هم کار کنند تا خودت بگویی پنل محصولات حذف شود. --- ## الف) یک نسخه پایلوت (مثلاً همکار) جای `DOMAIN` دامنه همان نسخه را بگذار (همان دامنه داخل سوپرادمین). ### ۱) اگر قبلاً روی همکار `SUPERADMIN_SMS_*` گذاشتی، موقتاً خاموش کن روی سرور همکار در `.env` این خطوط را کامنت یا حذف کن: ```env # SUPERADMIN_SMS_BASE_URL=... # SUPERADMIN_SMS_SHARED_SECRET=... # SUPERADMIN_SMS_DOMAIN=... ``` بعد: ```bash php artisan config:clear php artisan config:cache ``` علت: تا قبل از مهاجرت، پنل همکار باید همان داده واقعی محلی را نشان بدهد. ### ۲) اعداد فعلی همکار را یادداشت کن از پنل پیامک ادمین همکار: - موجودی - قیمت هر پارت - وضعیت بلاک ### ۳) سوپرادمین را با کد جدید آپدیت کن روی سرور سوپرادمین (بعد از pull/build کد جدید): ```bash cd /var/www/superadmin/api pm2 restart superadmin-api ``` ### ۴) مهاجرت خشک (فقط نمایش، بدون نوشتن) روی سرور سوپرادمین، با دسترسی به MySQL همان نسخه همکار: ```bash cd /var/www/superadmin/api SMS_IMPORT_DRY_RUN=1 \ SMS_IMPORT_DOMAIN=DOMAIN \ SMS_IMPORT_PRODUCT=hamkar \ HAMKAR_DB_HOST=IP_یا_127.0.0.1 \ HAMKAR_DB_PORT=3306 \ HAMKAR_DB_USER=USER \ HAMKAR_DB_PASSWORD='PASS' \ HAMKAR_DB_DATABASE=DBNAME \ npm run prisma:import-sms-from-product ``` اگر گفت `SKIP: sms_panel=me` → این نسخه پنل اختصاصی دارد؛ مهاجرت لازم نیست. اگر دامنه پیدا نشد → دامنه را با همان مقدار داخل سوپرادمین چک کن. ### ۵) مهاجرت واقعی همان دستور بدون `SMS_IMPORT_DRY_RUN=1`: ```bash SMS_IMPORT_DOMAIN=DOMAIN \ SMS_IMPORT_PRODUCT=hamkar \ HAMKAR_DB_HOST=... \ HAMKAR_DB_PORT=3306 \ HAMKAR_DB_USER=... \ HAMKAR_DB_PASSWORD='...' \ HAMKAR_DB_DATABASE=... \ npm run prisma:import-sms-from-product ``` ### ۶) در سوپرادمین چک کن همان نسخه را باز کن؛ موجودی/تعرفه/بلاک باید با یادداشت مرحله ۲ یکی باشد. ### ۷) کد همکار را آپدیت کن و remote را روشن کن بعد از دیپلوی کد جدید همکار، در `.env` همکار: ```env SUPERADMIN_SMS_BASE_URL=https://adm.montzar.ir/api/remote/sms SUPERADMIN_SMS_SHARED_SECRET=همان_رمز_سوپرادمین # فقط اگر APP_URL دامنه درست ندارد: # SUPERADMIN_SMS_DOMAIN=DOMAIN ``` ```bash php artisan config:clear php artisan config:cache ``` ### ۸) تست موازی 1. پنل همکار و سوپرادمین را باز کن → موجودی یکی باشد 2. در سوپرادمین شارژ کن → در همکار رفرش → باید یکی شود 3. در همکار تعرفه/بلاک عوض کن → در سوپرادمین همان را ببین 4. یک SMS تست بفرست → موجودی هر دو کم شود --- ## ب) خانگی (چندنسخه‌ای روی یک سرور) قانون: هر نسخه = یک Tenant = یک MySQL = یک `.env` = یک `SUPERADMIN_SMS_DOMAIN`. روی یک سرور فیزیکی ممکن است چند نصب باشد؛ هرگز یک دامنه/DB مشترک برای همه نگذار. ### ب-۱) موجودی‌گیری از سوپرادمین ```bash cd /var/www/superadmin/api git pull npm run prisma:inventory-khanegi-sms # یا: SMS_INVENTORY_FORMAT=json SMS_INVENTORY_OUT=/tmp/khanegi-sms-inventory.json \ npm run prisma:inventory-khanegi-sms ``` خروجی `syncStatus` / `nextAction` و لیست `multiVersionHosts` را نگه دار. ### ب-۲) فایل اهداف ایمپورت از روی موجودی، فایل واقعی بساز (از روی نمونه): `prisma/khanegi-sms-targets.example.json` → مثلاً `prisma/khanegi-sms-targets.json` برای هر دامنه، MySQL **همان نسخه** را بگذار. پایلوت را `"pilot": true` کن. ### ب-۳) پایلوت: dry-run سپس import ```bash cd /var/www/superadmin/api # فقط پایلوت، خشک SMS_IMPORT_TARGETS=./prisma/khanegi-sms-targets.json \ SMS_IMPORT_ONLY_PILOT=1 \ SMS_IMPORT_DRY_RUN=1 \ npm run prisma:import-sms-batch # واقعی SMS_IMPORT_TARGETS=./prisma/khanegi-sms-targets.json \ SMS_IMPORT_ONLY_PILOT=1 \ npm run prisma:import-sms-batch ``` یا تک‌دامنه: ```bash bash deploy/khanegi-sms-import-one.sh DOMAIN 127.0.0.1 DB_USER 'DB_PASS' DB_NAME bash deploy/khanegi-sms-import-one.sh DOMAIN 127.0.0.1 DB_USER 'DB_PASS' DB_NAME --apply ``` بعد در UI سوپرادمین موجودی/تعرفه/بلاک را با پنل خانگی قبل از روشن کردن remote چک کن. ایمپورت موفق `tenants.sms_synced_at` را هم پر می‌کند. ### ب-۴) روشن کردن remote فقط روی `.env` همان نسخه مقدار `SMS_REMOTE_SHARED_SECRET` را از `/var/www/superadmin/api/.env` بردار، بعد روی سرور خانگی: ```bash # مسیر server همان نسخه bash /path/to/khanegi-sms-enable-remote.sh /var/www/CUSTOMER/server DOMAIN 'SHARED_SECRET' # یا دستی: # SUPERADMIN_SMS_BASE_URL=https://adm.montzar.ir/api/remote/sms # SUPERADMIN_SMS_SHARED_SECRET=... # SUPERADMIN_SMS_DOMAIN=DOMAIN php artisan config:clear && php artisan config:cache php artisan sms:superadmin-probe ``` ### ب-۵) rollout بقیه همان چرخه نسخه به نسخه (یا batch بدون `ONLY_PILOT`). `skip` / `sms_panel=me` / بدون wallet را جدا نگه دار. --- ## ج) نسخه‌هایی که هنوز فعال نشده‌اند - جدول `sms_wallets` ندارند یا خالی‌اند → اسکریپت skip می‌کند - `sms_panel=me` → skip - برای آن‌ها فعلاً کاری نکن تا خودت بگویی --- ## کار موازی تا اعلام تو تا وقتی بگویی «پنل همکار/خانگی لازم نیست»: - تغییر در **سوپرادمین** → با باز کردن پنل محصول هم دیده می‌شود (و در MySQL محلی هم mirror می‌شود) - تغییر در **پنل همکار/خانگی** → در سوپرادمین ذخیره می‌شود - ارسال SMS → کسر از سوپرادمین + mirror محلی بعد از اطمینان نهایی، پنل محصولات حذف می‌شود و فقط سوپرادمین می‌ماند.