Перейти к содержимому
DedicatedPHP Контакт

Как спроектировать закрытие SaaS-аккаунта с льготным периодом

Руководство о том, как разделить запрос, приостановку и окончательное закрытие, контролировать доступ и процессы и повторно активировать организацию без дублирования ресурсов.

Диаграмма состояний закрытия SaaS-аккаунта: от запроса до повторной активации или окончательного закрытия

Закрытие SaaS-аккаунта с льготным периодом — это не одна отложенная операция. Это процесс жизненного цикла, который должен координировать доступ, биллинг, автоматические задачи, интеграции и данные. Если приложение только сохраняет дату закрытия и проверяет её при входе в систему, другие процессы могут продолжать работать так, будто организация активна.

В проекте нужно явно определить, что означает каждый этап, кто может выполнять переход и какие последствия обратимы. Так отмена запроса не будет равнозначна восстановлению аккаунта с нуля, а наступление крайнего срока не будет зависеть от того, войдёт ли пользователь в систему снова.

Разделите запрос, приостановку и окончательное закрытие

Разделите запрос, приостановку и окончательное закрытие — guía visual de DedicatedPHP

Запрос выражает намерение: уполномоченный пользователь просит закрыть аккаунт. Приостановка определяет, что организация может делать, пока запрос находится в обработке. Окончательное закрытие запускает завершающие действия, которые могут включать отзыв учётных данных, остановку процессов и применение политики обработки данных. Это разные этапы, и их следует моделировать отдельно.

Важное продуктовое решение — определить, когда начинают ограничиваться доступы. Если доступ сохраняется до истечения срока, об этом нужно чётко сообщить и контролировать использование сервиса в этот период. Если ограничения вводятся сразу, льготный период предназначен для восстановления аккаунта, а не для обычного использования сервиса. Универсального варианта нет: выбор зависит от коммерческой модели, рисков и обязательств продукта.

Также необходимо определить последствия для биллинга и подписок. Закрытие аккаунта не обязательно отменяет внешнюю подписку, а отмена платежа не должна приводить к удалению организации. Уточните, какой источник истины используется для каждого решения, и не выводите операционный статус из отдельного события платёжного провайдера.

Определите состояния и допустимые переходы

Явная модель помогает интерфейсу, API и фоновым задачам применять одинаковые правила. В простом процессе можно использовать состояния active, deletion_requested, suspended и closed. Если приостановка происходит одновременно с подачей запроса, возможно, достаточно одного состояния запроса и атрибутов, описывающих ограничения. Не добавляйте состояния, которые не отражают реальных операционных различий.

Задокументируйте допустимые переходы. Например, активная организация может запросить закрытие; действующий запрос можно отменить; запрос с истёкшим сроком может перейти к окончательному закрытию. Как правило, закрытую организацию не следует открывать повторно той же операцией отмены: если предусмотрено восстановление, для него нужна отдельная процедура с чёткими ограничениями.

  • Записывайте, кто инициировал запрос, когда и через какой канал, а также дату окончания льготного периода.
  • Проверяйте права и текущее состояние на сервере, а не только в интерфейсе.
  • Отклоняйте повторные и параллельные запросы либо обрабатывайте их явно.
  • Сохраняйте изменения состояния атомарно, а побочные эффекты публикуйте с помощью надёжного шаблона, например transactional outbox.

В PHP-приложении централизуйте правила переходов в доменном сервисе или аналогичном слое. Контроллеры не должны напрямую менять несколько полей и рассчитывать, что все потребители поймут новую семантику. База данных должна хранить достаточно информации, чтобы ожидающий выполнения процесс мог определить нужное действие, не полагаясь на состояние предыдущего веб-запроса.

Ограничьте доступ и остановите ожидающие процессы

Определите доступные возможности для каждой роли на время льготного периода. Администратор может иметь право отменить закрытие и просматривать данные, необходимые для экспорта, тогда как доступ участников организации можно заблокировать. Если разрешён доступ только для чтения, укажите, какие ресурсы он охватывает и остаются ли доступны API, загрузки и административные функции. Те же ограничения должны действовать в интерфейсе, API и автоматизированных задачах.

Одной блокировки входа недостаточно. Токены доступа, API-ключи, активные сеансы и учётные данные интеграций могут продолжить работать. Определите, какие из них отозвать, какие приостановить, а какие временно сохранить. Если учётные данные отзываются, зафиксируйте это, чтобы повторная активация не зависела от уже недействующих секретов; возможно, потребуется сгенерировать их заново.

Проверьте очереди и запланированные задачи: например, рассылки, синхронизации, отчёты, webhooks и задачи биллинга. Перед операцией с внешними последствиями каждый процесс должен проверять актуальное состояние организации. Уже поставленные в очередь задачи можно отменить, приостановить или завершить согласно явно заданной политике. Не предполагайте, что изменение состояния аккаунта автоматически удалит сообщения из распределённой очереди.

Отмена задачи также должна быть идемпотентной. Повторный запуск задачи после сетевого сбоя не должен дублировать уведомление или операцию закрытия. Используйте идентификаторы событий, ключи идемпотентности или подходящие ограничения уникальности, а результаты записывайте, чтобы отличать безопасный повторный запуск от нового действия.

Обеспечьте безопасную отмену закрытия и повторную активацию

В течение льготного периода отмена запроса должна быть определённым переходом, а не процедурой, которая «откатывает всё» без проверки произошедшего. Операция должна подтвердить, что срок ещё не истёк, однократно обновить состояние и восстановить только те возможности, которые были приостановлены и по-прежнему актуальны.

Чтобы избежать дубликатов, не создавайте заново без разбора подписки, webhooks, запланированные задачи, рабочие пространства или учётные данные. Сохраняйте стабильные идентификаторы и отмечайте состояние каждого побочного эффекта. Если внешний компонент уже отключён, приложение должно уметь согласовать его состояние: проверить, существует ли он, контролируемо создать его заново или сообщить, что требуется действие вручную.

Идемпотентная повторная активация приводит к одному и тому же конечному состоянию, даже если её запросили несколько раз. Этого можно добиться с помощью транзакций для локальных изменений, операций обновления вместо безусловных вставок и стратегии повторных попыток для внешних систем. Если операция завершается ошибкой на середине, запишите, какие шаги выполнены, и обеспечьте возможность продолжить, не повторяя уже успешные.

Продумайте работу с данными, аудит и окончательное закрытие

Операционное закрытие и удаление данных — разные решения. Определите, что произойдёт с данными организации, резервными копиями, журналами аудита и информацией, которую нужно сохранить в силу юридических или договорных обязательств. Применимые сроки и основания зависят от контекста и юрисдикции; их следует согласовать с ответственными за конфиденциальность и соблюдение требований. В соответствии с применимой политикой сообщите клиенту, что именно будет удалено и сохранено и на какой срок.

После окончания льготного периода запланированный процесс должен находить ожидающие запросы и перед закрытием аккаунта повторно проверять их состояние и крайний срок. При частичном сбое система должна записать неудачный шаг и позволять возобновить выполнение. Флаг closed сам по себе не доказывает, что учётные данные отозваны или интеграции остановлены.

Сохраняйте историю запросов, отмен, изменений прав, завершающих операций и ошибок. Ограничьте доступ к этим записям и не включайте в них секреты или ненужные персональные данные. Оповещения должны указывать на случаи, когда превышено ожидаемое время, например на организации с истёкшим сроком, которые всё ещё активны, или на закрытия, блокируемые повторяющимися ошибками.

Контрольный список для тестирования процесса

Контрольный список для тестирования процесса — guía visual de DedicatedPHP
  • Пользователь без необходимых прав не может запросить или отменить закрытие.
  • Повторный запрос на закрытие не приводит к дублированию дат, событий или операций закрытия.
  • Роли имеют именно те возможности, которые предусмотрены на время льготного периода.
  • Сеансы, токены, API, очереди и интеграции учитывают состояние организации.
  • Отмена до истечения срока восстанавливает предусмотренный доступ, не дублируя процессы и ресурсы.
  • Запрос с истёкшим сроком нельзя отменить поздним запросом, а закрытие не выполняется дважды.
  • Частичные сбои и повторные попытки позволяют завершить закрытие без повторения внешних эффектов.
  • Правила хранения и удаления данных проверяются отдельно от операционной блокировки.

Также протестируйте одновременные изменения, задержки в очередях и ошибки внешних провайдеров. Признак согласованности проекта — не только надпись «аккаунт закрыт» на экране, но и то, что права, процессы, учётные данные и данные отражают одно и то же решение, а система может объяснить, как пришла к этому состоянию.

Хотите применить эти идеи в своем проекте?Давайте обсудим вашу PHP-платформу.
Посмотреть связанные услуги