show subaccounts in admin_info if any exist

SavagePeanut created

Change summary

forms/admin_plan_info.rb   |  7 ++++
lib/customer_info.rb       |  5 ++
lib/subaccount.rb          | 18 +++++++++++
test/test_admin_command.rb |  7 ++++
test/test_customer_info.rb | 64 ++++++++++++++++++++++++++++++++++++++++
5 files changed, 100 insertions(+), 1 deletion(-)

Detailed changes

forms/admin_plan_info.rb 🔗

@@ -10,3 +10,10 @@ field(
 	label: "Billing Customer Id",
 	value: @plan_info.billing_customer_id
 )
+
+unless @admin_info.subaccounts.empty?
+	table(
+		@admin_info.subaccounts,
+		customer_id: "Customer Id"
+	)
+end

lib/customer_info.rb 🔗

@@ -12,6 +12,7 @@ require_relative "customer_plan"
 require_relative "form_template"
 require_relative "promise_hash"
 require_relative "proxied_jid"
+require_relative "subaccount"
 
 class PlanInfo
 	extend Forwardable
@@ -115,6 +116,7 @@ class AdminInfo
 		call_info String
 		trust_level String
 		backend_jid String
+		subaccounts ArrayOf(::Subaccount), default: []
 	end
 
 	def self.for(
@@ -130,7 +132,8 @@ class AdminInfo
 			api: API.for(customer),
 			call_info: call_info(customer, call_attempt_repo),
 			trust_level: trust_level_repo.find(customer).then(&:to_s),
-			backend_jid: backend_repo.get(customer.customer_id).from_jid.to_s
+			backend_jid: backend_repo.get(customer.customer_id).from_jid.to_s,
+			subaccounts: Subaccount.get_subaccounts(customer.billing_customer_id)
 		).then(&method(:new))
 	end
 

lib/subaccount.rb 🔗

@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class Subaccount
+	value_semantics do
+		customer_id String
+	end
+
+	def initialize(customer_id)
+		@customer_id = customer_id
+	end
+
+	def self.get_subaccounts(parent_id)
+		DB.query_one(<<~SQL, parent_id)
+			SELECT customer_id FROM customer_plans WHERE parent_customer_id=$1
+	  SQL
+			.then { |rows| rows.map { |customer_id| Subaccount.new(customer_id) } }
+	end
+end

test/test_admin_command.rb 🔗

@@ -70,6 +70,12 @@ class AdminCommandTest < Minitest::Test
 				[String, "testuser"], default: {}
 			)
 
+			Subaccount::DB.expect(
+				:query_one,
+				EMPromise.resolve({}),
+				[String, "testuser"]
+			)
+
 			Command::COMMAND_MANAGER.expect(
 				:write,
 				EMPromise.resolve(q_form),
@@ -86,6 +92,7 @@ class AdminCommandTest < Minitest::Test
 		assert_mock customer_repo
 		assert_mock Command::COMMAND_MANAGER
 		assert_mock TrustLevelRepo::REDIS
+		assert_mock Subaccount::DB
 	end
 	em :test_no_user
 

test/test_customer_info.rb 🔗

@@ -17,6 +17,7 @@ PlanInfo::DB = FakeDB.new(
 		}
 	]
 )
+Subaccount::DB = Minitest::Mock.new
 
 class CustomerInfoTest < Minitest::Test
 	def test_info_does_not_crash
@@ -118,6 +119,12 @@ class CustomerInfoTest < Minitest::Test
 			[String, "test"]
 		)
 
+		Subaccount::DB.expect(
+			:query_one,
+			EMPromise.resolve({}),
+			[String, "test"]
+		)
+
 		cust = customer(sgx: sgx, plan_name: "test_usd")
 
 		trust_repo = Minitest::Mock.new
@@ -127,6 +134,7 @@ class CustomerInfoTest < Minitest::Test
 		assert_mock sgx
 		assert_mock trust_repo
 		assert_mock CustomerUsage::DB
+		assert_mock Subaccount::DB
 	end
 	em :test_admin_info_does_not_crash
 
@@ -147,6 +155,12 @@ class CustomerInfoTest < Minitest::Test
 			[String, "test"]
 		)
 
+		Subaccount::DB.expect(
+			:query_one,
+			EMPromise.resolve({}),
+			[String, "test"]
+		)
+
 		cust = customer(sgx: sgx, plan_name: "test_usd")
 
 		call_attempt_repo = Minitest::Mock.new
@@ -167,6 +181,7 @@ class CustomerInfoTest < Minitest::Test
 		assert_mock call_attempt_repo
 		assert_mock trust_repo
 		assert_mock CustomerUsage::DB
+		assert_mock Subaccount::DB
 	end
 	em :test_admin_info_with_tel_does_not_crash
 
@@ -192,6 +207,12 @@ class CustomerInfoTest < Minitest::Test
 		sgx.expect(:registered?, false)
 		sgx.expect(:fwd, CustomerFwd::None.new(uri: nil, timeout: nil))
 
+		Subaccount::DB.expect(
+			:query_one,
+			EMPromise.resolve({}),
+			[String, "test"]
+		)
+
 		plan = CustomerPlan.new("test", plan: nil, expires_at: nil)
 		cust = Customer.new(
 			"test",
@@ -206,6 +227,49 @@ class CustomerInfoTest < Minitest::Test
 		assert AdminInfo.for(cust, trust_level_repo: trust_repo).sync.form
 		assert_mock sgx
 		assert_mock trust_repo
+		assert_mock Subaccount::DB
 	end
 	em :test_inactive_admin_info_does_not_crash
+
+	def test_admin_info_subaccount_does_not_crash
+		sgx = Minitest::Mock.new
+		sgx.expect(:registered?, false)
+		fwd = CustomerFwd.for(uri: "tel:+12223334444", timeout: 15)
+		sgx.expect(:fwd, fwd)
+		sgx.expect(:registered?, false)
+
+		CustomerPlan::DB.expect(
+			:query_one,
+			EMPromise.resolve({ start_date: Time.now }),
+			[String, "test"]
+		)
+
+		CustomerUsage::DB.expect(
+			:query_one,
+			EMPromise.resolve({ charges: 0.to_d }),
+			[String, "test"]
+		)
+
+		Subaccount::DB.expect(
+			:query_one,
+			EMPromise.resolve({}),
+			[String, "parent"]
+		)
+
+		cust = customer(
+			sgx: sgx,
+			plan_name: "test_usd",
+			parent_customer_id: "parent"
+		)
+
+		trust_repo = Minitest::Mock.new
+		trust_repo.expect(:find, TrustLevel::Basement, [cust])
+
+		assert AdminInfo.for(cust, trust_level_repo: trust_repo).sync.form
+		assert_mock sgx
+		assert_mock trust_repo
+		assert_mock CustomerUsage::DB
+		assert_mock Subaccount::DB
+	end
+	em :test_admin_info_subaccount_does_not_crash
 end