plan.rb

 1# frozen_string_literal: true
 2
 3class Plan
 4	def self.for(plan_name)
 5		return plan_name if plan_name.is_a?(Plan)
 6
 7		plan = CONFIG[:plans].find { |p| p[:name] == plan_name }
 8		raise "No plan by that name" unless plan
 9
10		new(plan)
11	end
12
13	def initialize(plan)
14		@plan = plan
15	end
16
17	def name
18		@plan[:name]
19	end
20
21	def currency
22		@plan[:currency]
23	end
24
25	def monthly_price
26		BigDecimal(@plan[:monthly_price]) / 10000
27	end
28
29	def merchant_account
30		CONFIG[:braintree][:merchant_accounts].fetch(currency) do
31			raise "No merchant account for this currency"
32		end
33	end
34
35	def minute_limit
36		CallingLimit.new(Limit.for("minute", @plan[:minutes]))
37	end
38
39	def message_limit
40		Limit.for("message", @plan[:messages])
41	end
42
43	class Limit
44		def self.for(unit, from_config)
45			case from_config
46			when :unlimited
47				Unlimited.new(unit)
48			else
49				new(unit: unit, **from_config)
50			end
51		end
52
53		value_semantics do
54			unit String
55			included Integer
56			price Integer
57		end
58
59		def to_s
60			"#{included} #{unit}s " \
61			"(overage $#{'%.4f' % (price.to_d / 10000)} / #{unit})"
62		end
63
64		def to_d
65			included.to_d / 10000
66		end
67
68		class Unlimited
69			def initialize(unit)
70				@unit = unit
71			end
72
73			def to_s
74				"unlimited #{@unit}s"
75			end
76		end
77	end
78
79	class CallingLimit
80		def initialize(limit)
81			@limit = limit
82		end
83
84		def to_d
85			@limit.to_d
86		end
87
88		def to_s
89			"#{'$%.4f' % to_d} of calling credit per calendar month " \
90			"(overage $#{'%.4f' % (@limit.price.to_d / 10000)} / minute)"
91		end
92	end
93end