feat: test_mode toggle in admin + cache bump v10

- test_mode + test_phone columns in sms_campaign_settings (DB)
- Script reads test_mode from DB settings, not env vars
- Admin panel: toggle Test/Production mode with visual indicator
- test_mode=true (default): SMS only to test_phone
- test_mode=false: SMS to real customers
- Service worker cache v9 → v10 (fixes white screen)
This commit is contained in:
root 2026-06-23 08:58:59 +00:00
parent f264a53c0a
commit 4215001ab7
3 changed files with 48 additions and 4 deletions

View File

@ -1,8 +1,8 @@
const isLocalhost = self.location.hostname === "localhost" || self.location.hostname === "127.0.0.1";
if (!isLocalhost) {
const STATIC_CACHE = "construction-delivery-static-v9";
const RUNTIME_CACHE = "construction-delivery-runtime-v9";
const STATIC_CACHE = "construction-delivery-static-v10";
const RUNTIME_CACHE = "construction-delivery-runtime-v10";
const APP_SHELL_URLS = ["/", "/index.html", "/manifest.webmanifest", "/icons/icon-192.png", "/icons/icon-512.png"];
self.addEventListener("install", (event) => {

View File

@ -46,6 +46,10 @@ SMS_STATUS_URL = "https://sms.ru/sms/status"
LOG_FILE = "/var/log/supersam-sms-first.log"
# ТЕСТОВЫЙ РЕЖИМ — управляется из админки (sms_campaign_settings.test_mode)
# По умолчанию ВКЛЮЧЕН — SMS идут только на test_phone
# Мегаадмин выключает через админку → SMS идут реальным клиентам
# Коды, которые означают "в процессе" (ждём дальше)
IN_TRANSIT_CODES = {"100", "101", "102"}
# Код доставки
@ -87,6 +91,8 @@ def load_settings(conn):
"enabled": True,
"telegram_chat_id": "25164483",
"sms_api_id": SMS_API_ID,
"test_mode": True,
"test_phone": "79788382260",
}
return dict(row)
@ -287,8 +293,14 @@ def step_send_new(conn, settings):
sms_text = f"Ваш заказ готов. Согласуйте дату доставки по ссылке: {delivery_link}"
log.info(f"Sending SMS to {name} ({phone})")
sms_id, raw, code = send_sms(phone, sms_text, api_id)
# ТЕСТОВЫЙ РЕЖИМ: подменяем номер на тестовый
send_phone = phone
if settings.get("test_mode", True):
send_phone = settings.get("test_phone", "79788382260")
log.info(f"TEST MODE: sending to {send_phone} instead of {phone}")
log.info(f"Sending SMS to {name} (orig={phone}, send={send_phone})")
sms_id, raw, code = send_sms(send_phone, sms_text, api_id)
if sms_id:
log_id = insert_sms_log(conn,

View File

@ -178,6 +178,38 @@ export const SmsCampaignPanel = () => {
<span className="text-xs text-[var(--color-accent)]"> Сохранено</span>
)}
</div>
{/* Test / Production mode toggle */}
<div className={`mb-4 rounded-xl border p-3 ${settings.test_mode ? "border-[var(--color-warning)] bg-[rgba(191,123,33,0.08)]" : "border-[var(--color-accent)] bg-[var(--color-accent-soft)]"}`}>
<label className="flex items-center justify-between">
<div>
<div className="text-sm font-semibold text-[var(--color-text)]">
{settings.test_mode ? "🧪 Тестовый режим" : "🚀 Боевой режим"}
</div>
<div className="mt-0.5 text-xs text-[var(--color-text-muted)]">
{settings.test_mode
? `SMS отправляются только на тестовый номер: ${settings.test_phone || "—"}`
: "SMS отправляются реальным клиентам из базы"}
</div>
</div>
<button
type="button"
onClick={() => updateSetting("test_mode", !settings.test_mode)}
className={`relative h-7 w-12 rounded-full transition ${settings.test_mode ? "bg-[var(--color-warning)]" : "bg-[var(--color-accent)]"}`}
>
<span className={`absolute top-0.5 h-6 w-6 rounded-full bg-white shadow transition ${settings.test_mode ? "left-0.5" : "left-[22px]"}`} />
</button>
</label>
{settings.test_mode && (
<div className="mt-3">
<SettingField
label="Тестовый номер телефона"
value={settings.test_phone || ""}
onChange={(v) => updateSetting("test_phone", v)}
/>
</div>
)}
</div>
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3">
<SettingField
label="Пауза между проверками (сек)"