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:
parent
f264a53c0a
commit
4215001ab7
|
|
@ -1,8 +1,8 @@
|
||||||
const isLocalhost = self.location.hostname === "localhost" || self.location.hostname === "127.0.0.1";
|
const isLocalhost = self.location.hostname === "localhost" || self.location.hostname === "127.0.0.1";
|
||||||
|
|
||||||
if (!isLocalhost) {
|
if (!isLocalhost) {
|
||||||
const STATIC_CACHE = "construction-delivery-static-v9";
|
const STATIC_CACHE = "construction-delivery-static-v10";
|
||||||
const RUNTIME_CACHE = "construction-delivery-runtime-v9";
|
const RUNTIME_CACHE = "construction-delivery-runtime-v10";
|
||||||
const APP_SHELL_URLS = ["/", "/index.html", "/manifest.webmanifest", "/icons/icon-192.png", "/icons/icon-512.png"];
|
const APP_SHELL_URLS = ["/", "/index.html", "/manifest.webmanifest", "/icons/icon-192.png", "/icons/icon-512.png"];
|
||||||
|
|
||||||
self.addEventListener("install", (event) => {
|
self.addEventListener("install", (event) => {
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,10 @@ SMS_STATUS_URL = "https://sms.ru/sms/status"
|
||||||
|
|
||||||
LOG_FILE = "/var/log/supersam-sms-first.log"
|
LOG_FILE = "/var/log/supersam-sms-first.log"
|
||||||
|
|
||||||
|
# ТЕСТОВЫЙ РЕЖИМ — управляется из админки (sms_campaign_settings.test_mode)
|
||||||
|
# По умолчанию ВКЛЮЧЕН — SMS идут только на test_phone
|
||||||
|
# Мегаадмин выключает через админку → SMS идут реальным клиентам
|
||||||
|
|
||||||
# Коды, которые означают "в процессе" (ждём дальше)
|
# Коды, которые означают "в процессе" (ждём дальше)
|
||||||
IN_TRANSIT_CODES = {"100", "101", "102"}
|
IN_TRANSIT_CODES = {"100", "101", "102"}
|
||||||
# Код доставки
|
# Код доставки
|
||||||
|
|
@ -87,6 +91,8 @@ def load_settings(conn):
|
||||||
"enabled": True,
|
"enabled": True,
|
||||||
"telegram_chat_id": "25164483",
|
"telegram_chat_id": "25164483",
|
||||||
"sms_api_id": SMS_API_ID,
|
"sms_api_id": SMS_API_ID,
|
||||||
|
"test_mode": True,
|
||||||
|
"test_phone": "79788382260",
|
||||||
}
|
}
|
||||||
return dict(row)
|
return dict(row)
|
||||||
|
|
||||||
|
|
@ -287,8 +293,14 @@ def step_send_new(conn, settings):
|
||||||
|
|
||||||
sms_text = f"Ваш заказ готов. Согласуйте дату доставки по ссылке: {delivery_link}"
|
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:
|
if sms_id:
|
||||||
log_id = insert_sms_log(conn,
|
log_id = insert_sms_log(conn,
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,38 @@ export const SmsCampaignPanel = () => {
|
||||||
<span className="text-xs text-[var(--color-accent)]">✓ Сохранено</span>
|
<span className="text-xs text-[var(--color-accent)]">✓ Сохранено</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</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">
|
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3">
|
||||||
<SettingField
|
<SettingField
|
||||||
label="Пауза между проверками (сек)"
|
label="Пауза между проверками (сек)"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue