New customers on certain domains should automatically get a certain parent

Stephen Paul Weber created

Change summary

config-schema.dhall        |  2 ++
config.dhall.sample        |  1 +
lib/customer.rb            | 26 ++++++++++++--------------
lib/customer_plan.rb       | 16 +++++++++++++++-
lib/customer_repo.rb       |  2 +-
test/test_customer_repo.rb | 29 +++++++++++++++++++++++++++++
test/test_helper.rb        |  6 ++++++
7 files changed, 66 insertions(+), 16 deletions(-)

Detailed changes

config-schema.dhall 🔗

@@ -29,6 +29,8 @@
 , ogm_web_root : Text
 , onboarding_domain : Text
 , oxr_app_id : Text
+, parented_domains :
+    List { mapKey : Text, mapValue : { customer_id : Text, plan_name : Text } }
 , payable : Text
 , plans :
     List

config.dhall.sample 🔗

@@ -86,6 +86,7 @@ in
 	rev_ai_token = "",
 	upstream_domain = "example.net",
 	approved_domains = toMap { `example.com` = Some "customer_id" },
+	parented_domains = toMap { `example.com` = { customer_id = "customer_id", plan_name = "usd" } },
 	keepgo = Some { api_key = "", access_token = "" },
 	simpleswap_api_key = "",
 	reachability_senders = [ "+14445556666" ],

lib/customer.rb 🔗

@@ -35,19 +35,22 @@ class Customer
 	               :transactions
 
 	def self.extract(customer_id, jid, **kwargs)
-		klass, *keys = if kwargs[:parent_customer_id]
-			[ChildCustomer, :parent_customer_id]
-		else
-			[Customer]
-		end
-
-		klass.new(
+		(kwargs[:parent_customer_id] ? ChildCustomer : Customer).new(
 			customer_id, jid,
 			plan: CustomerPlan.extract(customer_id, **kwargs),
-			**kwargs.slice(:balance, :sgx, :tndetails, :feature_flags, *keys)
+			**kwargs.slice(:balance, :sgx, :tndetails, :feature_flags)
 		)
 	end
 
+	def self.created(customer_id, jid, **kwargs)
+		plan = CustomerPlan.default(customer_id, jid)
+		if plan.parent_customer_id
+			ChildCustomer.new(customer_id, jid, plan: plan, **kwargs)
+		else
+			new(customer_id, jid, plan: plan, **kwargs)
+		end
+	end
+
 	def initialize(
 		customer_id,
 		jid,
@@ -129,13 +132,8 @@ class Customer
 	end
 
 	class ChildCustomer < Customer
-		def initialize(*args, parent_customer_id:, **kwargs)
-			super(*args, **kwargs)
-			@parent_customer_id = parent_customer_id
-		end
-
 		def billing_customer_id
-			@parent_customer_id
+			@plan.parent_customer_id
 		end
 
 		def billing_customer(repo=CustomerRepo.new)

lib/customer_plan.rb 🔗

@@ -8,7 +8,8 @@ require_relative "plan"
 class CustomerPlan
 	extend Forwardable
 
-	attr_reader :expires_at, :auto_top_up_amount, :monthly_overage_limit
+	attr_reader :expires_at, :auto_top_up_amount, :monthly_overage_limit,
+	            :parent_customer_id
 
 	def_delegator :@plan, :name, :plan_name
 	def_delegators :@plan, :currency, :merchant_account, :monthly_price,
@@ -18,6 +19,19 @@ class CustomerPlan
 		new(customer_id, plan: plan_name&.then(&Plan.method(:for)), **kwargs)
 	end
 
+	def self.default(customer_id, jid)
+		config = CONFIG[:parented_domains][Blather::JID.new(jid).domain]
+		if config
+			self.for(
+				customer_id,
+				plan_name: config[:plan_name],
+				parent_customer_id: config[:customer_id]
+			)
+		else
+			new(customer_id)
+		end
+	end
+
 	def self.extract(customer_id, **kwargs)
 		self.for(
 			customer_id,

lib/customer_repo.rb 🔗

@@ -102,7 +102,7 @@ class CustomerRepo
 			).then do |redis_result|
 				raise "Saving new customer to redis failed" unless redis_result == 1
 
-				Customer.new(cid, Blather::JID.new(jid), sgx: new_sgx(cid))
+				Customer.created(cid, Blather::JID.new(jid), sgx: new_sgx(cid))
 			end
 		end
 	end

test/test_customer_repo.rb 🔗

@@ -148,6 +148,35 @@ class CustomerRepoTest < Minitest::Test
 	end
 	em :test_create
 
+	def test_create_parented
+		redis = Minitest::Mock.new
+		braintree = Minitest::Mock.new
+		repo = mkrepo(redis: redis, braintree: braintree)
+		braintree_customer = Minitest::Mock.new
+		braintree.expect(:customer, braintree_customer)
+		braintree_customer.expect(
+			:create,
+			EMPromise.resolve(
+				OpenStruct.new(success?: true, customer: OpenStruct.new(id: "test"))
+			)
+		)
+		redis.expect(
+			:msetnx,
+			EMPromise.resolve(1),
+			[
+				"jmp_customer_id-test@parented.example.com", "test",
+				"jmp_customer_jid-test", "test@parented.example.com"
+			]
+		)
+		result = repo.create("test@parented.example.com").sync
+		assert_kind_of Customer::ChildCustomer, result
+		assert_equal "1234", result.billing_customer_id
+		assert_mock braintree
+		assert_mock braintree_customer
+		assert_mock redis
+	end
+	em :test_create_parented
+
 	def test_put_lidb_name
 		post = stub_request(
 			:post,

test/test_helper.rb 🔗

@@ -113,6 +113,12 @@ CONFIG = {
 		"approved.example.com": nil,
 		"refer.example.com": "refer_to"
 	},
+	parented_domains: {
+		"parented.example.com" => {
+			customer_id: "1234",
+			plan_name: "test_usd"
+		}
+	},
 	bandwidth_site: "test_site",
 	bandwidth_peer: "test_peer",
 	keepgo: { api_key: "keepgokey", access_token: "keepgotoken" },