Represent plan limit details as a useful object

Stephen Paul Weber created

Change summary

lib/customer.rb      |  4 ++--
lib/customer_plan.rb |  3 ++-
lib/plan.rb          | 40 ++++++++++++++++++++++++++++++++++++++++
test/test_helper.rb  |  4 +++-
test/test_plan.rb    | 11 +++++++++++
5 files changed, 58 insertions(+), 4 deletions(-)

Detailed changes

lib/customer.rb 🔗

@@ -22,8 +22,8 @@ class Customer
 	attr_reader :customer_id, :balance, :jid, :tndetails
 
 	def_delegators :@plan, :active?, :activate_plan_starting_now, :bill_plan,
-	               :currency, :merchant_account, :plan_name,
-	               :auto_top_up_amount, :monthly_overage_limit
+	               :currency, :merchant_account, :plan_name, :minute_limit,
+	               :message_limit, :auto_top_up_amount, :monthly_overage_limit
 	def_delegators :@sgx, :register!, :registered?, :set_ogm_url,
 	               :fwd, :transcription_enabled
 	def_delegators :@usage, :usage_report, :message_usage, :incr_message_usage

lib/customer_plan.rb 🔗

@@ -11,7 +11,8 @@ class CustomerPlan
 	attr_reader :expires_at, :auto_top_up_amount, :monthly_overage_limit
 
 	def_delegator :@plan, :name, :plan_name
-	def_delegators :@plan, :currency, :merchant_account, :monthly_price
+	def_delegators :@plan, :currency, :merchant_account, :monthly_price,
+	               :minute_limit, :message_limit
 
 	def self.for(customer_id, plan_name: nil, **kwargs)
 		new(customer_id, plan: plan_name&.then(&Plan.method(:for)), **kwargs)

lib/plan.rb 🔗

@@ -29,4 +29,44 @@ class Plan
 			raise "No merchant account for this currency"
 		end
 	end
+
+	def minute_limit
+		Limit.for("minute", @plan[:minutes])
+	end
+
+	def message_limit
+		Limit.for("message", @plan[:messages])
+	end
+
+	class Limit
+		def self.for(unit, from_config)
+			case from_config
+			when :unlimited
+				Unlimited.new(unit)
+			else
+				new(unit: unit, **from_config)
+			end
+		end
+
+		value_semantics do
+			unit String
+			included Integer
+			price Integer
+		end
+
+		def to_s
+			"#{included} #{unit}s " \
+			"(overage $#{'%.4f' % (price.to_d / 10000)} / #{unit})"
+		end
+
+		class Unlimited
+			def initialize(unit)
+				@unit = unit
+			end
+
+			def to_s
+				"unlimited #{@unit}s"
+			end
+		end
+	end
 end

test/test_helper.rb 🔗

@@ -71,7 +71,9 @@ CONFIG = {
 		{
 			name: "test_usd",
 			currency: :USD,
-			monthly_price: 10000
+			monthly_price: 10000,
+			messages: :unlimited,
+			minutes: { included: 120, price: 87 }
 		},
 		{
 			name: "test_bad_currency",

test/test_plan.rb 🔗

@@ -23,4 +23,15 @@ class PlanTest < Minitest::Test
 			Plan.for("test_bad_currency").merchant_account
 		end
 	end
+
+	def test_message_limit
+		assert_equal "unlimited messages", Plan.for("test_usd").message_limit.to_s
+	end
+
+	def test_minute_limit
+		assert_equal(
+			"120 minutes (overage $0.0087 / minute)",
+			Plan.for("test_usd").minute_limit.to_s
+		)
+	end
 end