一种将客户从每周 1 次升级到 3 次再到 5 次的 DRYer 方法(即日期数学!)
A DRYer way to upgrade customer from 1 to 3 to 5 times a week (i.e., Date math!)
这是对人们来说非常明显的事情之一,但在代码方面我正在为如何编写它而苦苦挣扎。客户可以选择 3 个计划之一:
- 每周一次 (1) - 星期一,每件产品 15 美元(或一周 15 美元)
- 每周三次 (3) - 周三、周五,每件产品 12 美元(或一周 36 美元)
- 每周五次 (5) - 周一、周二、周三、周四、周五,每件产品 10 美元(或一周 50 美元)
升级逻辑简化如下:
- 如果客户从 1 升级到 3,对于已经付款的每周一,我们现在需要为该周的关联周三、周五添加 plan_dates,并为 $12 * 2 添加一个 Stripe InvoiceItem = 24 美元
- 如果客户从 1 升级到 5,对于已经付款的每周一,我们现在需要为该周的相关周二、周三、周四、周五添加 plan_dates,并添加一个 Stripe InvoiceItem 10 美元 * 4 = 40 美元
- 如果客户从 3 升级到 5,对于已经付款的每周一,我们现在需要为该周的关联 Th、Fri 添加 plan_dates,并添加一个 Stripe InvoiceItem for $10 * 2 = 20 美元
"every Monday already paid for"在代码中是一个数组array_of_mondays
。从那里开始,我一团糟,我想不出如何擦干...
prices = {1=>15, 3=>12, 5=>10}
array_of_mondays.each do |m|
if current_plan == 1 && new_plan == 3
self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(3, 0, m))
self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(5, 0, m))
Stripe::InvoiceItem.create(
customer: self.user.stripe_customer_id,
amount: (new_plan – current_plan) * prices[new_plan],
currency: “usd”
)
elsif current_plan == 1 && new_plan == 5
self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(2, 0, m))
self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(3, 0, m))
self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(4, 0, m))
self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(5, 0, m))
Stripe::InvoiceItem.create(
customer: self.user.stripe_customer_id,
amount: (new_plan – current_plan) * prices[new_plan],
currency: “usd”
)
elsif current_plan == 3 && new_plan == 5
self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(4, 0, m))
self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(5, 0, m))
Stripe::InvoiceItem.create(
customer: self.user.stripe_customer_id,
amount: (new_plan – current_plan) * prices[new_plan],
currency: “usd”
)
end
end
我使用的方法 date_of_next_X_day_Y_days_out_from_Z_start
有助于确定实际日期:
def date_of_next_X_day_Y_days_out_from_Z_start(wday, number_of_days, start_date)
number_of_days = number_of_days.to_i
wday = wday.to_i
day_ahead = start_date + number_of_days.days
(day_ahead) + ((7 - day_ahead.wday + wday) % 7).days
#returns Date object
end
换句话说,它正在做的是说创建一个 plan_date
和 ddate
是下周二,从指定的周一(例如,下周二)开始 0 天
好吧,实际上我只是一时灵机一动,想到了一个可能的答案,但很想听听其他人的意见:
prices = {1=>15, 3=>12, 5=>10}
dates_to_be_created = { [1,3] => [3,5], [1,5] => [2,3,4,5], [3,5] => [4,5] }
array_of_mondays.each do |m|
dates_to_be_created[[current_plan,new_plan]].each do |d|
self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(d, 0, m))
end
Stripe::InvoiceItem.create(
customer: self.user.stripe_customer_id,
amount: (new_plan – current_plan) * prices[new_plan],
currency: “usd”
)
end
这是对人们来说非常明显的事情之一,但在代码方面我正在为如何编写它而苦苦挣扎。客户可以选择 3 个计划之一:
- 每周一次 (1) - 星期一,每件产品 15 美元(或一周 15 美元)
- 每周三次 (3) - 周三、周五,每件产品 12 美元(或一周 36 美元)
- 每周五次 (5) - 周一、周二、周三、周四、周五,每件产品 10 美元(或一周 50 美元)
升级逻辑简化如下:
- 如果客户从 1 升级到 3,对于已经付款的每周一,我们现在需要为该周的关联周三、周五添加 plan_dates,并为 $12 * 2 添加一个 Stripe InvoiceItem = 24 美元
- 如果客户从 1 升级到 5,对于已经付款的每周一,我们现在需要为该周的相关周二、周三、周四、周五添加 plan_dates,并添加一个 Stripe InvoiceItem 10 美元 * 4 = 40 美元
- 如果客户从 3 升级到 5,对于已经付款的每周一,我们现在需要为该周的关联 Th、Fri 添加 plan_dates,并添加一个 Stripe InvoiceItem for $10 * 2 = 20 美元
"every Monday already paid for"在代码中是一个数组array_of_mondays
。从那里开始,我一团糟,我想不出如何擦干...
prices = {1=>15, 3=>12, 5=>10}
array_of_mondays.each do |m|
if current_plan == 1 && new_plan == 3
self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(3, 0, m))
self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(5, 0, m))
Stripe::InvoiceItem.create(
customer: self.user.stripe_customer_id,
amount: (new_plan – current_plan) * prices[new_plan],
currency: “usd”
)
elsif current_plan == 1 && new_plan == 5
self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(2, 0, m))
self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(3, 0, m))
self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(4, 0, m))
self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(5, 0, m))
Stripe::InvoiceItem.create(
customer: self.user.stripe_customer_id,
amount: (new_plan – current_plan) * prices[new_plan],
currency: “usd”
)
elsif current_plan == 3 && new_plan == 5
self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(4, 0, m))
self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(5, 0, m))
Stripe::InvoiceItem.create(
customer: self.user.stripe_customer_id,
amount: (new_plan – current_plan) * prices[new_plan],
currency: “usd”
)
end
end
我使用的方法 date_of_next_X_day_Y_days_out_from_Z_start
有助于确定实际日期:
def date_of_next_X_day_Y_days_out_from_Z_start(wday, number_of_days, start_date)
number_of_days = number_of_days.to_i
wday = wday.to_i
day_ahead = start_date + number_of_days.days
(day_ahead) + ((7 - day_ahead.wday + wday) % 7).days
#returns Date object
end
换句话说,它正在做的是说创建一个 plan_date
和 ddate
是下周二,从指定的周一(例如,下周二)开始 0 天
好吧,实际上我只是一时灵机一动,想到了一个可能的答案,但很想听听其他人的意见:
prices = {1=>15, 3=>12, 5=>10}
dates_to_be_created = { [1,3] => [3,5], [1,5] => [2,3,4,5], [3,5] => [4,5] }
array_of_mondays.each do |m|
dates_to_be_created[[current_plan,new_plan]].each do |d|
self.plan_dates.create(ddate: date_of_next_X_day_Y_days_out_from_Z_start(d, 0, m))
end
Stripe::InvoiceItem.create(
customer: self.user.stripe_customer_id,
amount: (new_plan – current_plan) * prices[new_plan],
currency: “usd”
)
end