ЛОКАЛЬНАЯ ДЕМОНСТРАЦИЯ НАПОМИНАНИЙ ОБ ОПЛАТЕ
Исследовательский срез 04.10.2026. Локальная сборка 05.10.2026 МСК.
Часовой пояс синтетического примера Europe/Moscow.
Основное синтетическое время: 2026-10-04T12:00:00+03:00.
Для проверки следующего периода есть отдельное событие 2026-11-04T12:00:00+03:00.

Все счета, события и суммы вымышлены. Контактов, реквизитов, ключей и настоящих адресатов нет.
Скрипт использует только стандартную библиотеку Python, включая zoneinfo.
Для Python 3.9+ требуется системная база часовых поясов с Europe/Moscow.
Сетевых библиотек, внешних вызовов, импортов CRM/платформы и расписания нет.

Состав:
- demo-input.json: 16 независимых сценариев, 41 событие и явная политика этапов.
- demo-expected.json: заранее заданные ожидания по событиям и счётчикам.
- demo-run.py: последовательный локальный расчёт и сверка ожиданий.
- demo-result.json: фактический первый прогон.
- demo-state.json: сохранённый журнал счетов, оплат и этапов.
- demo-replay-result.json: фактический повтор с тем же журналом.
- demo-readme.txt: эта инструкция.
- demo-files.sha256: хеши перечисленных файлов, кроме самого манифеста.

ПЕРВЫЙ ПРОГОН
Распакуйте архив в отдельный каталог и откройте терминал в нём.
Имя fresh-state.json должно быть новым: файла до первого запуска не должно существовать.

python3 demo-run.py --input demo-input.json --state fresh-state.json --result first-output.json --expected demo-expected.json

Ожидается код завершения 0, passed:true, 16 сценариев, 41 событие,
newPrepared:13 и simulatedChannelCalls:2.
Содержимое first-output.json должно побайтно совпасть с demo-result.json.

ПОВТОР С ПОСТОЯННЫМ ЖУРНАЛОМ

python3 demo-run.py --input demo-input.json --state fresh-state.json --result replay-output.json --replay-check

Ожидается код завершения 0, passed:true, newPrepared:0 и simulatedChannelCalls:0.
Можно воспроизвести только повтор, указав сохранённый demo-state.json вместо fresh-state.json.
Содержимое replay-output.json должно совпасть с demo-replay-result.json.

ПРОВЕРКИ
Первый проект и повтор этапа; частичная и полная оплата; повтор одного платежа;
пауза/полная оплата после подготовки; изменение срока; неизвестный результат;
ошибка источника до/после подготовки; будущий этап; отменённый счёт;
частичная оплата после подготовки; accepted заглушки; новый период и старый проект.

Ожидания написаны отдельно от расчёта. Несовпадение ожиданий даёт код 1 и failures в JSON.
Один сценарий не является одним сообщением: часть событий обновляет синтетический источник.
13 проектов и 2 вызова заглушки не являются письмами, отправкой или доставкой.
accepted означает только смоделированный ответ заглушки. unknown требует ручного разбора.
Состояний delivered и read в демонстрации нет. deliveryChecked:false.

ОГРАНИЧЕНИЯ
Это один процесс и обычный JSON-файл, без блокировок, БД, очереди и проверки аварийной записи.
Демонстрация не защищает от одновременной работы двух процессов и падения при сохранении файла.
Не подтверждены работа транспорта, подлинность внешних событий, доставка, прочтение или влияние на оплаты.
Перед реальным каналом нужны постоянный журнал с уникальным ключом и атомарным резервированием,
повторное чтение непосредственно перед действием, права доступа и отдельная проверка сбоев.
Сохраняется окно между чтением и внешней отправкой: оплата может поступить в этот момент.
В демо изменившийся подготовленный проект отменяется. Ручное пересогласование/возобновление не реализовано.
Не включайте реальные отправки, подставляя в этот файл клиентские контакты.
