сложная архитектурная проблема, включающая регулярные платежи и будущие события - PullRequest
5 голосов
/ 05 ноября 2010

Я ищу руководство о том, как разработать элегантное решение для того, что стало немного сложной задачей.Хотя я использую Ruby (и Rails), я думаю, что моя проблема в значительной степени архитектурная, хотя мой выбор языка, очевидно, оказывает влияние с точки зрения предложений, связанных с библиотеками и т. Д., Поэтому язык остается актуальным.

В любом случае, в двух словах: мое приложение содержит объекты, представляющие членство, принадлежащие людям, которые являются членами фитнес-центров.Членство содержит серию периодических платежей.Некоторые членства автоматически возобновляются в конце срока их полномочий, в то время как другие этого не делают.

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

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

Пока все хорошо.Что усложняет ситуацию, так это дополнительные требования:

  • администраторы могут «заморозить» членство (приостановить их) на определенное время, после чего они автоматически активируются (например, чтобы представлять людей, которые идутуехать в отпуск на определенный период времени).Я могу заблокировать членство прямо сейчас и возобновить его позже, или я могу запланировать замораживание, установив дату замораживания в определенный момент в будущем, а также дату повторной активации (примечание: всегда дата повторной активации, что немного упрощает процесс.)

  • администраторы могут отменить членство либо прямо сейчас, либо установив отмену в будущем.(Будущие отмены еще не созданы.)

  • администраторы могут возместить членство, что аналогично отмене, за исключением того, что возвращаются все прошлые платежи.

С этим трудно справиться, это влияние на регулярные платежи.Когда вы замораживаете членство, повторяющиеся платежи должны «растягиваться» вокруг периода замораживания, чтобы период времени, который представляет замораживание, не оплачивался.С этим как концептуально, так и программно сложно справиться.Платежи, например, могут продлеваться на разные периоды (т. Е. Каждый платеж для того, кто платит каждую вторую неделю, платит за две недели членства), и дата отмены может быть где угодно в пределах периода, который покрывает платеж.

Для замораживания я использовал подход, в котором объект членства содержит несколько дат, а именно «freeze_on» и «thaw_on» для обработки периода замораживания.Тем не менее, клиент теперь хочет и в будущем отмены, и я заметил некоторые ошибки с функцией замораживания, что заставляет меня поверить, что мне нужно пересмотреть мой подход.

Я обдумываю изменения, чтобы будущие события моглибыть запланированным, но не влияют на часть повторяющихся платежей приложения.Идея состояла бы в том, чтобы поставить в очередь определенные события.Например, замораживание в будущем будет выполнено путем помещения в очередь события замораживания в конкретную дату и оттаивания в последующую дату (эти два события будут связаны в одно «запланированное замораживание» с точки зрения пользователя).Будущее аннулирование будет обрабатываться аналогично.

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

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

Еще одна вещь, на которую следует обратить внимание, заключается в том, что регулярные платежи за членство с запланированными сроками (то есть без ежемесячного автоматического продления) должнысуществуют как записи базы данных, которые можно редактировать (перемещать во времени, корректировать цену), поэтому использование временных выражений (как предлагает Мартин Фаулер) не подходит для этой проблемы, насколько мне известно.Я понимаю, что мое предлагаемое решение очереди событий не будет отображать пользователю изменения, которые могут произойти с любыми существующими повторяющимися платежами, но я думаю, что могу с этим смириться.

не штрих-код сканирования, этоqr код

Торонто, дайте нам своих творческих людей

Редактировать: Чтобы ответить на два замечательных предложения ниже (в полях для комментариев практически отсутствует уровень детализации)):

Крис Робисон:

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

  2. Да, дата продления меняется - она ​​продвигается вперед на длину замораживания.Таким образом, если замораживание длится две недели, оно продвигает платеж на две недели вперед.Чтобы сделать вещи особенно сложными, в некоторых компаниях платежи могут быть сняты только в определенные даты - например, некоторые клубы обрабатывают платежи только 1-го и 15-го числа каждого месяца.Поэтому, когда даты переносятся, для этих клубов им приходится «привязываться» к определенной дате.

Можете ли вы объяснить более подробно, почему эти правила влияют на организацию событий, а не на управлениеоплата подписки?

Меня интересует ваша концепция таблицы амортизации.Это в основном именно то, что я уже построил - годичное членство с ежемесячными платежами создает 12, а еженедельно - 52 - и у каждого из них есть сумма, налог и т. Д., Связанные с ними, наряду с государственным аппаратом, который управляетСостояния "в ожидании", "оплачено", "не выполнено" и "возмещено".

Часть, с которой я борюсь, - это реакция этой таблицы на события.Прямо сейчас, если вы установите замораживание, это немедленно повлияет на таблицу, изменив даты платежей.Установите замораживание в середине таблицы, и это подтолкнет платежи вперед.Это звучит эффективно, но на самом деле это довольно сложно и сложно управлять.Как ваша идея таблицы амортизации может улучшить эту ситуацию?

Arsen7:

Это похоже на очередь событий, которую я предложил изначально.Мне кажется очевидным, что вы работали с такими вещами раньше (я был впечатлен вашей проверкой ошибок на дату обработки, это отличная идея, и я собираюсь реализовать ее как можно скорее), поэтому я надеюсь, что вы сможете объяснитьВаше предложение чуть более подробно.

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

Мне кажется, что это отличный способ упростить мое приложение, но мне интересно, как пользователи это воспримут.Как бы я им указал, что график платежей, который они просматривали, когда было запланировано замораживание, больше не является точным графиком, но изменится, когда произойдет замораживание?

Ответы [ 2 ]

3 голосов
/ 05 ноября 2010

Допустимо ли применять схему, используемую в банковской сфере, когда вы обрабатываете все операции по счету один раз в день?Каждый объект может иметь набор (будущих) операций, таких как периоды замораживания, и каждый день объект должен принимать простое решение, например: «Должен ли я истечь сегодня или нет?»

Хорошая часть заключается в том,что такая ежедневная обработка очень проста в программировании.Кроме того, странные правила продления (на случай, если вы захотите их) просты в разработке: «это пятница? Это последнее в этом месяце?Msgstr ".

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

Считайте, что это псевдокод:

def process(day)
  raise "Already processed or missed a day" unless day == last_processed_day + 1

  check_expiration day
  check_frozen day
  check_anything day
  #...

  self.last_processed_day = day
  self.save!
end

ОТВЕТ:

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

Мне кажется, что это отличный способ упростить мое приложение, но мне интересно, как пользователи это воспримут.Как бы я им указал, что график платежей, который они просматривали, когда было запланировано замораживание, больше не является точным графиком, но изменится, как только произойдет замораживание?

«Ежедневная обработка»«Схема помогает вам быстро реагировать на вопросы, требующие сложных вычислений.

У вас есть три« группы »: текущее состояние (часто задаваемые вопросы), история (почти никогда не меняющаяся, задается относительно редко) и будущее.

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

Если ваши пользователи будут часто задавать вопросы о будущем (и, как вы сказали, они будут), «обработка»может также создать своего рода кеш для этих вопросов.Например: найдите (рассчитайте) следующую дату платежа и запишите ее в вспомогательную таблицу (расписание).

Главное, что вам нужно сделать, - это решить, какие вопросы будут задавать пользователи, и будут лиВы можете рассчитать ответы «на лету» или вам нужно подготовить ответ.

В банке (разумеется, разном), если вы спросите о текущем балансе, они могут дать вамответ, который был правдой в начале дня.«Лучшие» банки скажут вам, что утром у вас был X $, но теперь есть еще Y $, ожидающий учета.

Итак, если вы поместите стоп-запись в очередь событий, вы можете позвонитьметод, который будет обновлять расписание сразу.Та же самая процедура (или очень похожая) будет или может быть вызвана в ежедневной процедуре обработки.

1 голос
/ 06 ноября 2010

На ум приходит пара вопросов:

  1. Может ли заморозиться период времени менее месяца?
  2. Если да, меняется ли дата продления? Или как применяется ежемесячный платеж за неполный месяц?

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

Одним из способов решения проблем подписки является создание таблицы амортизации платежей по подписке. Если они платят ежемесячно в течение года, двенадцать платежей помещаются в очередь в таблице. У клиента в неделю может быть 52 платежа в таблице за тот же год. Каждый раз, когда наступает дата продления, после проверки наличия замораживания применяется следующий платеж.

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

Ответить

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...