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 self.for_registration(plan_name)
14 plan = self.for(plan_name)
15 raise "No registration plan by that name" unless plan.allow_register?
16
17 plan
18 end
19
20 def initialize(plan)
21 @plan = plan
22 end
23
24 def name
25 @plan[:name]
26 end
27
28 def currency
29 @plan[:currency]
30 end
31
32 def monthly_price
33 BigDecimal(@plan[:monthly_price]) / 10000
34 end
35
36 def subaccount_discount
37 BigDecimal(@plan[:subaccount_discount] || 0) / 10000
38 end
39
40 def allow_register?
41 !!@plan[:allow_register]
42 end
43
44 def merchant_account
45 CONFIG[:braintree][:merchant_accounts].fetch(currency) do
46 raise "No merchant account for this currency"
47 end
48 end
49
50 def minute_limit
51 CallingLimit.new(Limit.for("minute", @plan[:minutes]))
52 end
53
54 def message_limit
55 Limit.for("message", @plan[:messages])
56 end
57
58 class Limit
59 def self.for(unit, from_config)
60 case from_config
61 when :unlimited
62 Unlimited.new(unit)
63 else
64 new(unit: unit, **from_config)
65 end
66 end
67
68 value_semantics do
69 unit String
70 included Integer
71 price Integer
72 end
73
74 def to_s
75 "#{included} #{unit}s " \
76 "(overage $#{'%.4f' % (price.to_d / 10000)} / #{unit})"
77 end
78
79 def to_d
80 included.to_d / 10000
81 end
82
83 class Unlimited
84 def initialize(unit)
85 @unit = unit
86 end
87
88 def to_s
89 "unlimited #{@unit}s"
90 end
91 end
92 end
93
94 class CallingLimit
95 def initialize(limit)
96 @limit = limit
97 end
98
99 def to_d
100 @limit.to_d
101 end
102
103 def to_s
104 "#{'$%.4f' % to_d} of calling credit per calendar month " \
105 "(overage $#{'%.4f' % (@limit.price.to_d / 10000)} / minute)"
106 end
107 end
108end