feat(sms): текст SMS по типу отгрузки — свои шаблоны для доставки и самовывоза
Раньше текст был зашит в кампании и всегда говорил про доставку; настраиваемый
в админке sms_text_template не читался скриптами вообще. Сначала выяснилось,
что всем 909 pickup-группам уходило «Согласуйте дату доставки по ссылке».
- sms_campaign_settings.sms_text_template_pickup (новая колонка) + значения
sms_text_template = «…дату доставки…», pickup = «…дату самовывоза…»
(supabase/sms_text_templates_pickup.sql = миграция с фактическими текстами)
- sms_first_campaign / sms_second_campaign / sms_paid_storage_campaign:
build_sms_text(group, settings) — шаблон выбирается по og.delivery_type,
{link} подставляется ссылкой; приоритет профиль города (режим «Уведомление»)
→ шаблон кампании → дефолт скрипта
- вторая SMS и платное хранение тоже получили pickup-вариант (кампании были
выключены, поэтому в текстах жил только «доставка»)
- SmsCampaignPanel: два поля ввода (📦 Доставка / 🏪 Самовывоз) + длины и
предпросмотр с подставленной ссылкой + пояснение приоритета
- service-worker v117 (обязательный бамп при деплое фронта)
This commit is contained in:
parent
ece302d512
commit
cf5bf31008
|
|
@ -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-v116";
|
const STATIC_CACHE = "construction-delivery-static-v117";
|
||||||
const RUNTIME_CACHE = "construction-delivery-runtime-v116";
|
const RUNTIME_CACHE = "construction-delivery-runtime-v117";
|
||||||
const APP_SHELL_URLS = ["/", "/client", "/index.html", "/manifest.webmanifest", "/icons/icon-192.png", "/icons/icon-512.png"];
|
const APP_SHELL_URLS = ["/", "/client", "/index.html", "/manifest.webmanifest", "/icons/icon-192.png", "/icons/icon-512.png"];
|
||||||
|
|
||||||
// Only these are treated as cacheable static assets. Everything else
|
// Only these are treated as cacheable static assets. Everything else
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,49 @@ DELIVERY_ERROR_CODES = {"104", "105", "106", "107", "108", "130"}
|
||||||
# Коды превышения лимитов (нельзя повторять отправку — заблокируют)
|
# Коды превышения лимитов (нельзя повторять отправку — заблокируют)
|
||||||
LIMIT_ERROR_CODES = {"131", "132", "230", "231", "232"}
|
LIMIT_ERROR_CODES = {"131", "132", "230", "231", "232"}
|
||||||
|
|
||||||
|
# ─── Тексты SMS ──────────────────────────────────────────────────────────────
|
||||||
|
# Шаблоны живут в админке (sms_campaign_settings):
|
||||||
|
# sms_text_template — текст для ДОСТАВКИ
|
||||||
|
# sms_text_template_pickup — текст для САМОВЫВОЗА
|
||||||
|
# {link} подставляется ссылкой согласования. Пустой шаблон → DEFAULT_TEXT_*.
|
||||||
|
|
||||||
|
DEFAULT_TEXT_DELIVERY = "Ваш заказ готов. Согласуйте дату доставки по ссылке: {link}"
|
||||||
|
DEFAULT_TEXT_PICKUP = "Ваш заказ готов. Согласуйте дату самовывоза по ссылке: {link}"
|
||||||
|
DEFAULT_TEXT_NOTIFICATION = "Ваш заказ готов."
|
||||||
|
|
||||||
|
|
||||||
|
def is_pickup_group(group):
|
||||||
|
return (group.get("delivery_type") or "delivery").strip().lower() == "pickup"
|
||||||
|
|
||||||
|
|
||||||
|
def build_sms_text(group, settings):
|
||||||
|
"""Текст SMS по типу отгрузки: самовывоз → pickup-шаблон, доставка → обычный.
|
||||||
|
|
||||||
|
Приоритет:
|
||||||
|
1. текст профиля города (режим «Уведомление», sms_city_profiles) — как было;
|
||||||
|
2. шаблон кампании из админки для этого типа отгрузки;
|
||||||
|
3. дефолт по типу отгрузки.
|
||||||
|
"""
|
||||||
|
link = group.get("delivery_link") or ""
|
||||||
|
mode = (group.get("sms_mode") or "link").strip().lower()
|
||||||
|
profile_text = (group.get("sms_text_custom") or "").strip()
|
||||||
|
pickup = is_pickup_group(group)
|
||||||
|
template = (settings.get(
|
||||||
|
"sms_text_template_pickup" if pickup else "sms_text_template"
|
||||||
|
) or "").strip()
|
||||||
|
if not template:
|
||||||
|
template = DEFAULT_TEXT_PICKUP if pickup else DEFAULT_TEXT_DELIVERY
|
||||||
|
|
||||||
|
if mode == "notification":
|
||||||
|
if profile_text:
|
||||||
|
return profile_text
|
||||||
|
# уведомление без ссылки: шаблон годится, только если в нём нет {link}
|
||||||
|
if template and "{link}" not in template:
|
||||||
|
return template
|
||||||
|
return DEFAULT_TEXT_NOTIFICATION
|
||||||
|
|
||||||
|
return template.replace("{link}", link).strip()
|
||||||
|
|
||||||
# ─── Логирование ─────────────────────────────────────────────────────────────
|
# ─── Логирование ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
|
|
@ -369,15 +412,12 @@ def step_send_new(conn, settings):
|
||||||
log.info(f"Group {group_id}: already has recent SMS in log, skipping")
|
log.info(f"Group {group_id}: already has recent SMS in log, skipping")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Формируем текст SMS по режиму
|
# Формируем текст SMS по типу отгрузки (доставка / самовывоз) и режиму
|
||||||
|
sms_text = build_sms_text(group, settings)
|
||||||
if sms_mode == "notification":
|
if sms_mode == "notification":
|
||||||
# Уведомление без ссылки на согласование
|
log.info(f"Group {group_id}: NOTIFICATION mode (town={town}, type={delivery_type}): {sms_text!r}")
|
||||||
sms_text = custom_text if custom_text else "Ваш заказ готов."
|
|
||||||
log.info(f"Group {group_id}: NOTIFICATION mode (town={town}, type={delivery_type}), no link")
|
|
||||||
else:
|
else:
|
||||||
# Стандартный флоу — ссылка на согласование
|
log.info(f"Group {group_id}: LINK mode (town={town}, type={delivery_type}): {sms_text!r}")
|
||||||
sms_text = f"Ваш заказ готов. Согласуйте дату доставки по ссылке: {delivery_link}"
|
|
||||||
log.info(f"Group {group_id}: LINK mode (town={town}, type={delivery_type})")
|
|
||||||
|
|
||||||
# ТЕСТОВЫЙ РЕЖИМ: подменяем номер на тестовый
|
# ТЕСТОВЫЙ РЕЖИМ: подменяем номер на тестовый
|
||||||
send_phone = phone
|
send_phone = phone
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,33 @@ DELIVERED_CODE = "103"
|
||||||
DELIVERY_ERROR_CODES = {"104", "105", "106", "107", "108", "130"}
|
DELIVERY_ERROR_CODES = {"104", "105", "106", "107", "108", "130"}
|
||||||
LIMIT_ERROR_CODES = {"131", "132", "230", "231", "232"}
|
LIMIT_ERROR_CODES = {"131", "132", "230", "231", "232"}
|
||||||
|
|
||||||
|
# ─── Тексты SMS ──────────────────────────────────────────────────────────────
|
||||||
|
# Шаблоны живут в админке (sms_campaign_settings):
|
||||||
|
# sms_text_template — текст для ДОСТАВКИ
|
||||||
|
# sms_text_template_pickup — текст для САМОВЫВОЗА
|
||||||
|
# {link} подставляется ссылкой согласования. Пустой шаблон → DEFAULT_TEXT_*.
|
||||||
|
|
||||||
|
DEFAULT_TEXT_DELIVERY = (
|
||||||
|
"Ваш заказ переведён на платное хранение. Стоимость: 300 ₽/день. "
|
||||||
|
"Заберите заказ или согласуйте доставку: {link}"
|
||||||
|
)
|
||||||
|
DEFAULT_TEXT_PICKUP = (
|
||||||
|
"Ваш заказ переведён на платное хранение. Стоимость: 300 ₽/день. "
|
||||||
|
"Заберите заказ со склада или согласуйте дату самовывоза: {link}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def build_sms_text(group, settings):
|
||||||
|
"""Текст SMS о платном хранении по типу отгрузки."""
|
||||||
|
link = group.get("delivery_link") or ""
|
||||||
|
pickup = (group.get("delivery_type") or "delivery").strip().lower() == "pickup"
|
||||||
|
template = (settings.get(
|
||||||
|
"sms_text_template_pickup" if pickup else "sms_text_template"
|
||||||
|
) or "").strip()
|
||||||
|
if not template:
|
||||||
|
template = DEFAULT_TEXT_PICKUP if pickup else DEFAULT_TEXT_DELIVERY
|
||||||
|
return template.replace("{link}", link).strip()
|
||||||
|
|
||||||
# ─── Логирование ─────────────────────────────────────────────────────────────
|
# ─── Логирование ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
|
|
@ -195,7 +222,7 @@ def get_groups_to_send(conn):
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
SELECT og.id, og.group_key, og.customer_name, og.customer_phone,
|
SELECT og.id, og.group_key, og.customer_name, og.customer_phone,
|
||||||
og.customer_phone_normalized, og.delivery_link, og.notification_status,
|
og.customer_phone_normalized, og.delivery_link, og.notification_status,
|
||||||
og.paid_storage_at
|
og.paid_storage_at, og.delivery_type, og.town
|
||||||
FROM order_groups og
|
FROM order_groups og
|
||||||
LEFT JOIN sms_city_profiles scp ON scp.city = og.town
|
LEFT JOIN sms_city_profiles scp ON scp.city = og.town
|
||||||
WHERE og.delivery_status = 'paid_storage'
|
WHERE og.delivery_status = 'paid_storage'
|
||||||
|
|
@ -321,11 +348,8 @@ def step_send_new(conn, settings):
|
||||||
log.info(f"Group {group_id}: already has recent paid_storage SMS, skipping")
|
log.info(f"Group {group_id}: already has recent paid_storage SMS, skipping")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
sms_text = (
|
sms_text = build_sms_text(group, settings)
|
||||||
f"Ваш заказ переведён на платное хранение. "
|
log.info(f"Group {group_id}: paid_storage SMS ({group.get('delivery_type') or 'delivery'}): {sms_text!r}")
|
||||||
f"Стоимость: 300 ₽/день. "
|
|
||||||
f"Заберите заказ или согласуйте доставку: {delivery_link}"
|
|
||||||
)
|
|
||||||
|
|
||||||
send_phone = phone
|
send_phone = phone
|
||||||
if settings.get("test_mode", True):
|
if settings.get("test_mode", True):
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,27 @@ DELIVERY_ERROR_CODES = {"104", "105", "106", "107", "108", "130"}
|
||||||
# Коды превышения лимитов (нельзя повторять отправку — заблокируют)
|
# Коды превышения лимитов (нельзя повторять отправку — заблокируют)
|
||||||
LIMIT_ERROR_CODES = {"131", "132", "230", "231", "232"}
|
LIMIT_ERROR_CODES = {"131", "132", "230", "231", "232"}
|
||||||
|
|
||||||
|
# ─── Тексты SMS ──────────────────────────────────────────────────────────────
|
||||||
|
# Шаблоны живут в админке (sms_campaign_settings):
|
||||||
|
# sms_text_template — текст для ДОСТАВКИ
|
||||||
|
# sms_text_template_pickup — текст для САМОВЫВОЗА
|
||||||
|
# {link} подставляется ссылкой согласования. Пустой шаблон → DEFAULT_TEXT_*.
|
||||||
|
|
||||||
|
DEFAULT_TEXT_DELIVERY = "Ваш заказ готов к доставке. Выберите дату доставки по ссылке: {link}"
|
||||||
|
DEFAULT_TEXT_PICKUP = "Ваш заказ готов к самовывозу. Выберите дату самовывоза по ссылке: {link}"
|
||||||
|
|
||||||
|
|
||||||
|
def build_sms_text(group, settings):
|
||||||
|
"""Текст второй SMS по типу отгрузки: самовывоз → pickup-шаблон, иначе обычный."""
|
||||||
|
link = group.get("delivery_link") or ""
|
||||||
|
pickup = (group.get("delivery_type") or "delivery").strip().lower() == "pickup"
|
||||||
|
template = (settings.get(
|
||||||
|
"sms_text_template_pickup" if pickup else "sms_text_template"
|
||||||
|
) or "").strip()
|
||||||
|
if not template:
|
||||||
|
template = DEFAULT_TEXT_PICKUP if pickup else DEFAULT_TEXT_DELIVERY
|
||||||
|
return template.replace("{link}", link).strip()
|
||||||
|
|
||||||
# ─── Логирование ─────────────────────────────────────────────────────────────
|
# ─── Логирование ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
|
|
@ -215,7 +236,8 @@ def get_groups_to_send(conn, max_attempts):
|
||||||
with conn.cursor(cursor_factory=RealDictCursor) as cur:
|
with conn.cursor(cursor_factory=RealDictCursor) as cur:
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
SELECT og.id, og.group_key, og.customer_name, og.customer_phone,
|
SELECT og.id, og.group_key, og.customer_name, og.customer_phone,
|
||||||
og.customer_phone_normalized, og.delivery_link, og.notification_status
|
og.customer_phone_normalized, og.delivery_link, og.notification_status,
|
||||||
|
og.delivery_type, og.town
|
||||||
FROM order_groups og
|
FROM order_groups og
|
||||||
LEFT JOIN sms_city_profiles scp ON scp.city = og.town
|
LEFT JOIN sms_city_profiles scp ON scp.city = og.town
|
||||||
WHERE og.delivery_status = 'pending_confirmation'
|
WHERE og.delivery_status = 'pending_confirmation'
|
||||||
|
|
@ -401,7 +423,8 @@ def step_send_new(conn, settings):
|
||||||
log.info(f"Group {group_id}: already has recent second SMS in log, skipping")
|
log.info(f"Group {group_id}: already has recent second SMS in log, skipping")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
sms_text = f"Ваш заказ готов к доставке. Выберите дату доставки по ссылке: {delivery_link}"
|
sms_text = build_sms_text(group, settings)
|
||||||
|
log.info(f"Group {group_id}: second SMS ({group.get('delivery_type') or 'delivery'}), town={group.get('town') or '—'}: {sms_text!r}")
|
||||||
|
|
||||||
# ТЕСТОВЫЙ РЕЖИМ
|
# ТЕСТОВЫЙ РЕЖИМ
|
||||||
send_phone = phone
|
send_phone = phone
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,15 @@ const CAMPAIGNS = [
|
||||||
|
|
||||||
const HAS_SETTINGS = ["first_sms", "second_sms", "manual", "paid_storage"];
|
const HAS_SETTINGS = ["first_sms", "second_sms", "manual", "paid_storage"];
|
||||||
|
|
||||||
|
// ── SMS text templates (доставка / самовывоз) ────────────────────────────────
|
||||||
|
const SMS_LINK_PREVIEW = "https://dost.supersamsev.ru/d/XXXXXX";
|
||||||
|
|
||||||
|
const renderSmsPreview = (template, emptyLabel) => {
|
||||||
|
const text = (template || "").trim();
|
||||||
|
if (!text) return emptyLabel;
|
||||||
|
return text.replace("{link}", SMS_LINK_PREVIEW);
|
||||||
|
};
|
||||||
|
|
||||||
// ── Days of week ─────────────────────────────────────────────────────────────
|
// ── Days of week ─────────────────────────────────────────────────────────────
|
||||||
const DAYS = [
|
const DAYS = [
|
||||||
{ num: 1, short: "Пн" },
|
{ num: 1, short: "Пн" },
|
||||||
|
|
@ -488,19 +497,43 @@ export const SmsCampaignPanel = () => {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* ── SMS text template ──────────────────────────────────────────── */}
|
{/* ── SMS text templates: доставка / самовывоз ───────────────────── */}
|
||||||
{!isManualCampaign && (
|
{!isManualCampaign && (
|
||||||
<div className="mb-4 rounded-xl border border-[var(--color-border)] bg-[var(--color-surface)] p-3">
|
<div className="mb-4 rounded-xl border border-[var(--color-border)] bg-[var(--color-surface)] p-3">
|
||||||
<div className="mb-2 text-xs font-semibold text-[var(--color-text)]">📝 Текст SMS</div>
|
<div className="mb-2 text-xs font-semibold text-[var(--color-text)]">📝 Текст SMS</div>
|
||||||
|
<div className="grid grid-cols-1 gap-3 lg:grid-cols-2">
|
||||||
|
<div>
|
||||||
|
<div className="mb-1 text-[11px] font-semibold text-[var(--color-text-muted)]">📦 Доставка</div>
|
||||||
<textarea
|
<textarea
|
||||||
value={settings.sms_text_template || ""}
|
value={settings.sms_text_template || ""}
|
||||||
onChange={(e) => updateSetting("sms_text_template", e.target.value)}
|
onChange={(e) => updateSetting("sms_text_template", e.target.value)}
|
||||||
rows={3}
|
rows={3}
|
||||||
className="w-full rounded-xl border border-[var(--color-border)] bg-[var(--color-surface)] px-3 py-2 text-xs text-[var(--color-text)] focus:border-[var(--color-accent)] focus:outline-none resize-y"
|
className="w-full rounded-xl border border-[var(--color-border)] bg-[var(--color-surface)] px-3 py-2 text-xs text-[var(--color-text)] focus:border-[var(--color-accent)] focus:outline-none resize-y"
|
||||||
placeholder="Текст SMS. Используйте {link} для подстановки ссылки"
|
placeholder="Ваш заказ готов. Согласуйте дату доставки по ссылке: {link}"
|
||||||
/>
|
/>
|
||||||
<div className="mt-1 text-[10px] text-[var(--color-text-muted)]">
|
<div className="mt-1 text-[10px] text-[var(--color-text-muted)]">
|
||||||
{"{link}"} будет заменён на ссылку доставки. Текущая длина: {(settings.sms_text_template || "").replace("{link}", "https://dost.supersamsev.ru/d/XXXXXX").length} символов
|
Текущая длина: {(settings.sms_text_template || "").replace("{link}", SMS_LINK_PREVIEW).length} символов
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="mb-1 text-[11px] font-semibold text-[var(--color-text-muted)]">🏪 Самовывоз</div>
|
||||||
|
<textarea
|
||||||
|
value={settings.sms_text_template_pickup || ""}
|
||||||
|
onChange={(e) => updateSetting("sms_text_template_pickup", e.target.value)}
|
||||||
|
rows={3}
|
||||||
|
className="w-full rounded-xl border border-[var(--color-border)] bg-[var(--color-surface)] px-3 py-2 text-xs text-[var(--color-text)] focus:border-[var(--color-accent)] focus:outline-none resize-y"
|
||||||
|
placeholder="Ваш заказ готов. Согласуйте дату самовывоза по ссылке: {link}"
|
||||||
|
/>
|
||||||
|
<div className="mt-1 text-[10px] text-[var(--color-text-muted)]">
|
||||||
|
Текущая длина: {(settings.sms_text_template_pickup || "").replace("{link}", SMS_LINK_PREVIEW).length} символов
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mt-2 rounded-lg bg-[var(--color-surface-strong)] px-3 py-2 text-[10px] text-[var(--color-text-muted)]">
|
||||||
|
Текст выбирается по типу отгрузки: самовывоз → правый шаблон, доставка → левый. {"{link}"} заменяется ссылкой согласования.
|
||||||
|
<div className="mt-1">📦 Доставка: {renderSmsPreview(settings.sms_text_template, "— пусто, уйдёт стандартный текст кампании")}</div>
|
||||||
|
<div>🏪 Самовывоз: {renderSmsPreview(settings.sms_text_template_pickup, "— пусто, уйдёт стандартный текст кампании")}</div>
|
||||||
|
<div className="mt-1">Если у города в «SMS по городам» задан свой текст в режиме «Уведомление» — уходит он, и тогда шаблон применяется только если в нём нет {"{link}"}.</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
-- SMS-шаблоны по типу отгрузки: доставка / самовывоз
|
||||||
|
-- 2026-09-28
|
||||||
|
--
|
||||||
|
-- Раньше текст SMS был зашит в python-кампании и упоминал только доставку,
|
||||||
|
-- а редактируемый в админке sms_text_template не читался скриптами вообще.
|
||||||
|
--
|
||||||
|
-- Теперь:
|
||||||
|
-- sms_text_template — текст SMS для ДОСТАВКИ
|
||||||
|
-- sms_text_template_pickup — текст SMS для САМОВЫВОЗА
|
||||||
|
-- {link} подставляется ссылкой согласования; пустой шаблон → дефолт скрипта.
|
||||||
|
-- Приоритет: текст профиля города (режим «Уведомление», sms_city_profiles)
|
||||||
|
-- → шаблон кампании по типу отгрузки → дефолт.
|
||||||
|
|
||||||
|
ALTER TABLE sms_campaign_settings
|
||||||
|
ADD COLUMN IF NOT EXISTS sms_text_template_pickup text;
|
||||||
|
|
||||||
|
COMMENT ON COLUMN sms_campaign_settings.sms_text_template IS
|
||||||
|
'Текст SMS для доставки. {link} — ссылка согласования.';
|
||||||
|
COMMENT ON COLUMN sms_campaign_settings.sms_text_template_pickup IS
|
||||||
|
'Текст SMS для самовывоза. {link} — ссылка согласования.';
|
||||||
|
|
||||||
|
-- Значения = фактически отправляемые тексты на момент миграции
|
||||||
|
-- (до этого в first_sms/month лежал текст, который никуда не попадал)
|
||||||
|
UPDATE sms_campaign_settings SET
|
||||||
|
sms_text_template = 'Ваш заказ готов. Согласуйте дату доставки по ссылке: {link}',
|
||||||
|
sms_text_template_pickup = 'Ваш заказ готов. Согласуйте дату самовывоза по ссылке: {link}'
|
||||||
|
WHERE campaign_type = 'first_sms';
|
||||||
|
|
||||||
|
UPDATE sms_campaign_settings SET
|
||||||
|
sms_text_template = 'Ваш заказ готов к доставке. Выберите дату доставки по ссылке: {link}',
|
||||||
|
sms_text_template_pickup = 'Ваш заказ готов к самовывозу. Выберите дату самовывоза по ссылке: {link}'
|
||||||
|
WHERE campaign_type = 'second_sms';
|
||||||
|
|
||||||
|
UPDATE sms_campaign_settings SET
|
||||||
|
sms_text_template = 'Ваш заказ переведён на платное хранение. Стоимость: 300 ₽/день. Заберите заказ или согласуйте доставку: {link}',
|
||||||
|
sms_text_template_pickup = 'Ваш заказ переведён на платное хранение. Стоимость: 300 ₽/день. Заберите заказ со склада или согласуйте дату самовывоза: {link}'
|
||||||
|
WHERE campaign_type = 'paid_storage';
|
||||||
|
|
||||||
|
-- Проверка:
|
||||||
|
-- SELECT campaign_type, sms_text_template, sms_text_template_pickup
|
||||||
|
-- FROM sms_campaign_settings ORDER BY campaign_type;
|
||||||
Loading…
Reference in New Issue