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