# SMS Campaigns — Архитектура ## Обзор 4 сценария SMS-рассылок, каждый — systemd timer + service + Python скрипт. Сервер: `217.114.5.8`, скрипты в `/opt/supersam/scripts/`. ## Сценарии | Сценарий | Timer | Скрипт | Триггер | |----------|-------|--------|---------| | 1-я SMS | `sms-first-campaign.timer` | `sms_first_campaign.py` | `notification_status=link_ready` + `delivery_status=pending_confirmation` | | 2-я SMS | `sms-second-campaign.timer` | `sms_second_campaign.py` | `notification_status=first_sms_sent` + время прошло | | Ручное управление | `sms-manual-campaign.timer` | `sms_manual_campaign.py` | `second_sms_sent` + expired, или `link_ready` без SMS > 3ч, или `sms_sending` > 3ч | | Платное хранение | `sms-paid-storage-campaign.timer` | `sms_paid_storage_campaign.py` | `notification_status=paid_storage` + `paid_storage_at` | ## Timer конфигурация - `OnUnitActiveSec=600` — каждые 10 минут - `sms_timer_manager.sh` — управляет `timer_active` + `run_requested` + `needs_check` - `fcntl.flock` во всех скриптах — защита от параллельного запуска - `send_telegram` = no-op (pass) ## Логика retry - 2 попытки отправки SMS с интервалом ~90 мин - Если код SMS.ru не 103 (доставлено) после 2 попыток → `manual_required` - `effective_attempts = max(sms_attempts, total_failed)` — total_failed из всей истории `sms_campaign_log` - Код 231 (лимит одинаковых) → `send_failed`, НЕ повторять ## Рабочие часы | Параметр | 1/2 SMS | Manual | Paid Storage | |----------|---------|--------|-------------| | Часы | 8–21 | 8–21 | 8–21 | | Дни | Пн–Пт (1-5) | Пн–Сб (1-6) | Пн–Пт | | Проверка статусов | 24/7 | 24/7 | 24/7 | ## Настройки (БД `sms_campaign_settings`) - `test_mode` — false (1/2 SMS), true (manual/paid_storage) - `test_phone` — 79788382260 - `timer_active` — управляет включением systemd timer - `send_interval_seconds` — пауза между отправками (15с) - `work_hours_start/end` — 8/21 - `work_days` — "1,2,3,4,5" или "1,2,3,4,5,6" - `last_run_at` — обновляется при каждом запуске скрипта - `last_balance` — баланс sms.ru после последней отправки ## SMS.ru - Провайдер: sms.ru - Коды: 100 (в очереди), 102 (в пути), 103 (доставлено), 104-108 (ошибка), 231/232 (лимит) - API ключ хранится в `sms_campaign_settings` - Баланс отображается в UI (SmsCampaignPanel) ## UI (SmsCampaignPanel.jsx) - `getRunnerStatus(settings)` — показывает статус последнего запуска: - 🟢 Работает (Xм назад) — < 10 мин - 🟡 Xм назад — < 60 мин - 🔴 Xч назад — < 24ч - 🔴 Xд назад — > 24ч - `🔴 Xд назад` = `last_run_at` был более 24 часов назад - 4 вкладки кампаний, переключатель test/боевой, таймер on/off - Логи отправок, фильтры (дата, открытие ссылки), bulk delete - Edge function `check-sms-status` — мгновенная проверка SMS через sms.ru API ## State Machine ``` not_started → link_ready → sms_sending → checking → first_sms_sent → second_sms_sending → second_sms_sent → manual_required → confirmed → address_required → agreed → driver_assigned → loaded → on_route → delivered/picked_up ``` ## Ссылки - SMS ссылка содержит `?src=sms` — отличает открытие клиентом от админа - `opened_at` ставится только при `p_src='sms'` в RPC `get_delivery_invitation_by_token` - `access_count` растёт при любом открытии ## Деплой - Скрипты: напрямую в `/opt/supersam/scripts/` (не в Docker) - UI: SCP → `docker compose -f docker-compose.app.yml build --no-cache && up -d` - SW bump: `sed -i 's/construction-delivery-static-v[0-9]*/vNN/g' public/service-worker.js`