【发布时间】:2010-11-05 10:26:33
【问题描述】:
我正在寻找有关如何构建一个优雅的解决方案来解决这个已成为一个棘手问题的指导。尽管我使用的是 Ruby(和 Rails),但我认为我的问题主要是架构问题,尽管我对语言的选择显然会对涉及库等的建议产生影响,因此语言仍然相关。
总之,简而言之:我的应用程序包含代表会员资格的对象,属于健身设施的会员。会员资格包含一系列经常性付款。一些会员资格在其任期结束时自动续订,而另一些则不会。
例如,您的会员资格最初有效期为一年,之后每月续订。在应用程序中,创建此类成员会导致创建 12 次定期付款。最后一个月到期时,会员资格也会到期。每日 cron 任务负责根据已完成的付款导致会员资格过期。如果成员设置为自动更新,相同的 cron 任务将更新成员。
您的会员资格可能没有初始期限,只是按月或按周运行。这些以类似的方式工作,但减去了初始付款计划。
到目前为止一切顺利。让事情变得复杂的是额外的要求:
管理员可以“冻结”成员资格(将其搁置),在特定的时间段内,它们会自动重新激活(例如,代表在一段时间内休假的人)。我可以选择立即冻结会员资格并稍后重新激活,或者我可以选择通过在未来某个时间设置冻结日期以及重新激活日期来安排冻结(注意:总是 重新激活日期,这让事情变得更容易)。
管理员可以立即取消成员资格,也可以将取消设置为将来发生。 (未来的取消尚未建立。)
管理员可以退还会员资格,这与取消会员资格类似,只是退还任何过去的付款。
使这些问题难以处理的是对经常性付款的影响。当您冻结会员资格时,经常性付款必须在冻结期间“延长”,这样代表冻结的时间段就不会被支付。这在概念上和编程上都难以处理。例如,付款可能会延长不同的期限(即,每隔一周付款的人的每笔付款都会支付两周的会员资格),并且取消日期可能在付款涵盖的期限内的任何时间。
对于冻结,我采用了会员对象包含一些日期的方法,即“freeze_on”和“thaw_on”来处理冻结期。但是,客户现在也希望将来取消,而且我注意到冻结功能存在一些错误,这让我相信我需要重新考虑我的方法。
我正在考虑进行更改,以便可以安排未来的活动,但不会影响应用程序的定期付款部分。这个想法是将特定事件排队。例如,未来的冻结将通过在特定日期排队冻结事件和在后续日期的解冻事件来完成(从用户的角度来看,这两个事件将连接成一个“预定冻结”)。以后的取消也会以类似方式处理。
这种方法有一些好处,例如,如果您想取消未来的取消(我说的是那种烦人、棘手的事情),您可以简单地从事件队列中删除预定的取消。
然而,我有一种挥之不去的感觉,我可能只是从煎锅里跳进火里。我想知道是否有人可以就这个问题向我提供一些指导。我可以检查这类问题的设计模式或现有架构原则吗?
另外需要注意的是,具有预定期限的会员的定期付款(即不是逐月自动续订)必须作为可以编辑的数据库记录存在(及时移动,价格调整),因此使用时间表达式据我所知,(正如 Martin Fowler 所建议的)不适合这个问题。我意识到我提出的事件队列解决方案不会向用户显示任何现有定期付款会发生的变化,但我认为我可以接受。
不是scanlife条码,是二维码
多伦多,给我们你的创意人
编辑:回应以下两个很棒的建议(评论框不允许接近这种详细程度):
克里斯·罗宾逊:
是的,冻结期可以是任意长度,尽管在实践中我认为少于两周的情况很少见。但无论期限长短,任何解决方案都应该有效。
是的,续订日期发生了变化 - 它被冻结的长度提前。因此,如果冻结时间为两周,它会将付款提前两周。让事情变得特别棘手的是,在某些企业中,付款只能在特定日期提取 - 例如,一些俱乐部仅在每月 1 日和 15 日处理付款。所以当日期被推迟时,对于这些俱乐部来说,他们必须“快速”到一个特定的日期。
您能否更详细地解释为什么这些规则会影响事件队列,但不会影响订阅付款的管理?
我对您的摊销表概念很感兴趣。这基本上正是我已经建立的 - 一个为期一年的会员,每月付款创建 12 个,每周创建 52 个 - 每一个都有与之相关的金额、税收等,以及一个管理状态机“pending”、“paid”、“failed”和“refunded”状态。
我正在努力解决的问题是该表如何响应事件。现在,如果您设置冻结,它会通过更改付款日期立即影响表格。在表格中间设置冻结,它会推动付款。这听起来很有效,但实际上非常复杂且难以管理。您的摊销表想法将如何改善这种情况?
Arsen7:
这听起来像是我最初提出的事件队列。对我来说,您以前曾使用过类似的东西似乎很明显(您对处理日期的错误检查给我留下了深刻的印象,这是一个好主意,我打算尽快实施)所以我希望您能解释一下你的建议更详细一点。
具体来说,我想知道您的概念将如何处理我在原始问题中以及我刚刚在 Kris Robison 的回答中留下的评论中描述的经常性付款情况。如果我为给定的购买设置了定期付款时间表,并且在付款中间安排了冻结事件,那么付款时间表是否会保持不变,直到冻结日期成为当前日期,在该日期何时开始冻结并继续付款?
这可能是简化我的应用程序的好方法,但我想知道用户会如何看待它。我如何向他们表明他们在安排冻结时查看的付款时间表不再是准确的时间表,而是在冻结发生后会发生变化?
【问题讨论】:
-
好的,我刚刚编辑了答案,以便为编辑后的问题提供答案。 ;-) 请原谅我耽搁了这么久——我有几天比较忙。
标签: ruby-on-rails ruby design-patterns datetime architecture