Only show buy credit option if customer has a plan and a credit card

Stephen Paul Weber created

Change summary

lib/command_list.rb       | 36 ++++++++++++++++-------
lib/payment_methods.rb    |  8 +++++
test/test_command_list.rb | 63 +++++++++++++++++++++++++++++++++++++---
3 files changed, 91 insertions(+), 16 deletions(-)

Detailed changes

lib/command_list.rb 🔗

@@ -4,13 +4,11 @@ class CommandList
 	include Enumerable
 
 	def self.for(jid)
-		Customer.for_jid(jid).then(&:registered?).catch { nil }.then { |reg|
-			next [] unless reg
-			REDIS.get("catapult_fwd-#{reg.phone}").then { |fwd| [reg, fwd] }
-		}.then do |(reg, fwd)|
-			next RegisteredAndHasForwarding.new if reg && fwd
-			next Registered.new if reg
-			CommandList.new
+		Customer.for_jid(jid).catch { nil }.then do |customer|
+			EMPromise.resolve(customer&.registered?).catch { nil }.then do |reg|
+				next Registered.for(customer, reg.phone) if reg
+				CommandList.new
+			end
 		end
 	end
 
@@ -19,19 +17,28 @@ class CommandList
 	end
 
 	class Registered < CommandList
+		def self.for(customer, tel)
+			EMPromise.all([
+				REDIS.get("catapult_fwd-#{tel}"),
+				customer.plan_name ? customer.payment_methods : []
+			]).then do |(fwd, payment_methods)|
+				klass = Class.new(Registered)
+				klass.include(HasBilling) unless payment_methods.empty?
+				klass.include(HasForwarding) if fwd
+				klass.new
+			end
+		end
+
 		def each
 			super
 			yield node: "number-display", name: "Display JMP Number"
 			yield node: "configure-calls", name: "Configure Calls"
-			# TODO: don't show this item if no braintree methods available
-			# TODO: don't show this item if no plan for this customer
-			yield node: "buy-credit", name: "Buy account credit"
 			yield node: "usage", name: "Show Monthly Usage"
 			yield node: "reset sip account", name: "Create or Reset SIP Account"
 		end
 	end
 
-	class RegisteredAndHasForwarding < Registered
+	module HasForwarding
 		def each
 			super
 			yield(
@@ -40,4 +47,11 @@ class CommandList
 			)
 		end
 	end
+
+	module HasBilling
+		def each
+			super
+			yield node: "buy-credit", name: "Buy account credit"
+		end
+	end
 end

lib/payment_methods.rb 🔗

@@ -46,11 +46,19 @@ class PaymentMethods
 		}.merge(kwargs)
 	end
 
+	def empty?
+		false
+	end
+
 	class Empty
 		def default_payment_method; end
 
 		def to_list_single(*)
 			raise "No payment methods available"
 		end
+
+		def empty?
+			true
+		end
 	end
 end

test/test_command_list.rb 🔗

@@ -35,10 +35,17 @@ class CommandListTest < Minitest::Test
 		)
 		CommandList::Customer.expect(
 			:for_jid,
-			EMPromise.resolve(OpenStruct.new(registered?: OpenStruct.new(phone: "1"))),
+			EMPromise.resolve(OpenStruct.new(
+				registered?: OpenStruct.new(phone: "1"),
+				payment_methods: EMPromise.resolve([])
+			)),
 			["registered"]
 		)
-		assert_instance_of CommandList::Registered, CommandList.for("registered").sync
+		assert_equal(
+			["CommandList::Registered"],
+			CommandList.for("registered").sync
+			.class.ancestors.map(&:name).grep(/\ACommandList::/)
+		)
 	end
 	em :test_for_registered
 
@@ -50,13 +57,59 @@ class CommandListTest < Minitest::Test
 		)
 		CommandList::Customer.expect(
 			:for_jid,
-			EMPromise.resolve(OpenStruct.new(registered?: OpenStruct.new(phone: "1"))),
+			EMPromise.resolve(OpenStruct.new(
+				registered?: OpenStruct.new(phone: "1"),
+				payment_methods: EMPromise.resolve([])
+			)),
 			["registered"]
 		)
-		assert_instance_of(
-			CommandList::RegisteredAndHasForwarding,
+		assert_kind_of(
+			CommandList::HasForwarding,
 			CommandList.for("registered").sync
 		)
 	end
 	em :test_for_registered_with_fwd
+
+	def test_for_registered_with_billing
+		CommandList::REDIS.expect(
+			:get,
+			EMPromise.resolve(nil),
+			["catapult_fwd-1"]
+		)
+		CommandList::Customer.expect(
+			:for_jid,
+			EMPromise.resolve(OpenStruct.new(
+				registered?: OpenStruct.new(phone: "1"),
+				plan_name: "test",
+				payment_methods: EMPromise.resolve([:boop])
+			)),
+			["registered"]
+		)
+		assert_kind_of(
+			CommandList::HasBilling,
+			CommandList.for("registered").sync
+		)
+	end
+	em :test_for_registered_with_billing
+
+	def test_for_registered_with_forwarding_and_billing
+		CommandList::REDIS.expect(
+			:get,
+			EMPromise.resolve("tel:1"),
+			["catapult_fwd-1"]
+		)
+		CommandList::Customer.expect(
+			:for_jid,
+			EMPromise.resolve(OpenStruct.new(
+				registered?: OpenStruct.new(phone: "1"),
+				plan_name: "test",
+				payment_methods: EMPromise.resolve([:boop])
+			)),
+			["registered"]
+		)
+		result = CommandList.for("registered").sync
+		assert_kind_of CommandList::HasForwarding, result
+		assert_kind_of CommandList::HasBilling, result
+	end
+	em :test_for_registered_with_forwarding_and_billing
 end