|
1 | 1 | # Mailing |
2 | 2 |
|
3 | | -TODO |
| 3 | +## Назначение |
| 4 | + |
| 5 | +Модуль `mailing` отвечает за email-рассылки и шаблоны писем: хранение схем |
| 6 | +старой админской формы рассылки, подготовку данных письма, отправку сообщений |
| 7 | +через email backend и автоматические сценарии рассылок по партнерским |
| 8 | +программам. |
| 9 | + |
| 10 | +## Статус модуля |
| 11 | + |
| 12 | +Модуль используется в рабочих сценариях, но не подключен как публичный API. |
| 13 | +Основные активные точки использования: |
| 14 | + |
| 15 | +- celery-задача `run_program_mailings`; |
| 16 | +- старая форма рассылки из админки партнерских программ; |
| 17 | +- общие helper-функции отправки писем, которые используют другие модули. |
| 18 | + |
| 19 | +## Основные возможности |
| 20 | + |
| 21 | +- хранение схемы письма в `MailingSchema`; |
| 22 | +- рендеринг старой админской формы рассылки; |
| 23 | +- подготовка данных письма из формы или typed dataclass; |
| 24 | +- массовая отправка писем по строковому шаблону; |
| 25 | +- массовая отправка писем по Django template; |
| 26 | +- группировка писем батчами; |
| 27 | +- сценарные рассылки участникам партнерских программ; |
| 28 | +- логирование результата сценарных рассылок в `MailingScenarioLog`. |
| 29 | + |
| 30 | +## Архитектура |
| 31 | + |
| 32 | +- `mailing/models.py` - модели схем писем и логов сценарных рассылок. |
| 33 | +- `mailing/utils.py` - подготовка данных письма и низкоуровневые функции |
| 34 | + отправки. |
| 35 | +- `mailing/scenarios.py` - декларативное описание сценариев рассылки по |
| 36 | + программам. |
| 37 | +- `mailing/tasks.py` - celery-задача запуска сценариев. |
| 38 | +- `mailing/rendering.py` - подстановка базовых placeholders в темы и тексты. |
| 39 | +- `mailing/views.py` - старые views для формы рассылки; сейчас не подключены в |
| 40 | + публичный URLConf. |
| 41 | +- `mailing/urls.py` - старые routes формы рассылки, не подключенные в |
| 42 | + `procollab/urls.py`. |
| 43 | +- `mailing/tests/` - regression-тесты моделей, rendering/helpers и сценариев. |
| 44 | + |
| 45 | +## Ключевые сущности |
| 46 | + |
| 47 | +- `MailingSchema` - схема шаблона письма и HTML-шаблон для старой формы |
| 48 | + рассылки. |
| 49 | +- `MailingScenarioLog` - лог отправки сценарного письма конкретному участнику |
| 50 | + программы за конкретную дату. |
| 51 | +- `Scenario` - dataclass с кодом сценария, триггером, правилом выбора |
| 52 | + получателей, шаблоном и builder-контекстом. |
| 53 | +- `EmailDataToPrepare` - typed input для подготовки данных письма из кода. |
| 54 | + |
| 55 | +## API и внешние точки входа |
| 56 | + |
| 57 | +Публичных endpoints модуля `mailing` сейчас нет: `mailing.urls` не подключен в |
| 58 | +корневой `procollab/urls.py`. |
| 59 | + |
| 60 | +Связанные внешние точки: |
| 61 | + |
| 62 | +- `/anymail/` - webhook routes библиотеки Anymail; |
| 63 | +- админка партнерской программы вызывает `MailingTemplateRender` напрямую через |
| 64 | + custom admin view; |
| 65 | +- celery beat запускает `mailing.tasks.run_program_mailings` каждый день в |
| 66 | + 10:00. |
| 67 | + |
| 68 | +## Основные сценарии |
| 69 | + |
| 70 | +### 1. Сценарная рассылка по партнерским программам |
| 71 | + |
| 72 | +`run_program_mailings()` проходит по сценариям из `SCENARIOS`. |
| 73 | + |
| 74 | +Для каждого сценария: |
| 75 | + |
| 76 | +- вычисляется целевая дата; |
| 77 | +- выбираются программы по дате регистрации, окончанию регистрации или дедлайну |
| 78 | + подачи проекта; |
| 79 | +- выбираются получатели по правилу сценария; |
| 80 | +- создаются `MailingScenarioLog` в статусе `pending`; |
| 81 | +- письмо отправляется через `send_mass_mail_from_template`; |
| 82 | +- статус лога меняется на `sent` или `failed` по `anymail_status`. |
| 83 | + |
| 84 | +Повторная отправка за ту же дату не дублирует письма со статусом `pending` или |
| 85 | +`sent`. |
| 86 | + |
| 87 | +### 2. Старая админская рассылка |
| 88 | + |
| 89 | +`MailingTemplateRender` строит контекст формы: |
| 90 | + |
| 91 | +- доступные `MailingSchema`; |
| 92 | +- выбранные и невыбранные пользователи; |
| 93 | +- поля шаблона из JSON-схемы. |
| 94 | + |
| 95 | +Сейчас этот renderer используется из админки партнерских программ. |
| 96 | + |
| 97 | +### 3. Отправка письма из других модулей |
| 98 | + |
| 99 | +Другие модули могут подготовить `EmailDataToPrepare`, получить данные через |
| 100 | +`prepare_mail_data()` и отправить письмо через `send_mass_mail()`. |
| 101 | + |
| 102 | +Такой flow сейчас использует `vacancy.tasks.send_email`, который также |
| 103 | +переиспользуется партнерскими программами и оценками проектов. |
| 104 | + |
| 105 | +## Связи с другими модулями |
| 106 | + |
| 107 | +- `partner_programs` - сценарные рассылки выбирают программы и участников через |
| 108 | + selectors; админка программ использует старый renderer формы рассылки. |
| 109 | +- `vacancy` - задачи вакансий используют mailing helpers для email-уведомлений. |
| 110 | +- `project_rates` - переиспользует общий notification flow через |
| 111 | + `vacancy.tasks.send_email`. |
| 112 | +- `users` - получатели писем. |
| 113 | +- `anymail` / Unisender Go - фактическая отправка писем в production. |
| 114 | + |
| 115 | +## Ограничения и риски |
| 116 | + |
| 117 | +- `mailing/urls.py` содержит старые routes, но они не подключены наружу. |
| 118 | +- Если старые routes будут снова подключены, для них нужно отдельно проверить |
| 119 | + permissions и безопасность массовой отправки. |
| 120 | +- В `mailing/urls.py` есть историческая опечатка `template_fileds`; менять ее |
| 121 | + без проверки старого UI не стоит. |
| 122 | +- `vacancy.tasks.send_email` фактически является общим helper для уведомлений, |
| 123 | + но находится в модуле вакансий. |
| 124 | +- `MailingScenarioLog` пока не зарегистрирован в Django admin. |
| 125 | + |
| 126 | +## Тесты |
| 127 | + |
| 128 | +Текущие regression-тесты проверяют: |
| 129 | + |
| 130 | +- строковое представление `MailingSchema` и `MailingScenarioLog`; |
| 131 | +- подстановку placeholders в subject и template values; |
| 132 | +- контекст старого renderer формы рассылки; |
| 133 | +- подготовку данных письма из `EmailDataToPrepare`; |
| 134 | +- группировку писем батчами; |
| 135 | +- рендеринг и отправку писем по строковому шаблону; |
| 136 | +- отправку писем по Django template с `status_callback`; |
| 137 | +- выбор участников с неактивными аккаунтами для сценариев программ; |
| 138 | +- успешную сценарную рассылку без повторной отправки; |
| 139 | +- перевод сценарного лога в `failed` при ошибочном `anymail_status`. |
0 commit comments