New parented customer should save plan and get balance from parent

Stephen Paul Weber created

Change summary

lib/customer.rb            |  6 ++++--
lib/customer_plan.rb       |  5 +++--
lib/customer_repo.rb       |  2 +-
test/test_customer_repo.rb | 38 +++++++++++++++++++++++++++++++++++---
4 files changed, 43 insertions(+), 8 deletions(-)

Detailed changes

lib/customer.rb 🔗

@@ -42,10 +42,12 @@ class Customer
 		)
 	end
 
-	def self.created(customer_id, jid, **kwargs)
+	def self.created(customer_id, jid, repo:, **kwargs)
+		jid = Blather::JID.new(jid)
 		plan = CustomerPlan.default(customer_id, jid)
 		if plan.parent_customer_id
-			ChildCustomer.new(customer_id, jid, plan: plan, **kwargs)
+			# Parent may have a balance, so look it up
+			plan.save_plan!.then { repo.find(customer_id) }
 		else
 			new(customer_id, jid, plan: plan, **kwargs)
 		end

lib/customer_plan.rb 🔗

@@ -71,12 +71,13 @@ class CustomerPlan
 	end
 
 	def save_plan!
-		DB.exec_defer(<<~SQL, [@customer_id, plan_name])
+		DB.exec_defer(<<~SQL, [@customer_id, plan_name, @parent_customer_id])
 			INSERT INTO plan_log
-				(customer_id, plan_name, date_range)
+				(customer_id, plan_name, parent_customer_id, date_range)
 			VALUES (
 				$1,
 				$2,
+				$3,
 				tsrange(
 					LOCALTIMESTAMP - '2 seconds'::interval,
 					LOCALTIMESTAMP - '1 second'::interval

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.created(cid, Blather::JID.new(jid), sgx: new_sgx(cid))
+				Customer.created(cid, jid, sgx: new_sgx(cid), repo: self)
 			end
 		end
 	end

test/test_customer_repo.rb 🔗

@@ -7,6 +7,8 @@ class CustomerRepo
 	attr_reader :sgx_repo
 end
 
+CustomerPlan::DB = Minitest::Mock.new
+
 class CustomerRepoTest < Minitest::Test
 	FAKE_REDIS = FakeRedis.new(
 		# sgx-jmp customer
@@ -38,6 +40,12 @@ class CustomerRepoTest < Minitest::Test
 			"plan_name" => "test_usd",
 			"expires_at" => Time.now + 100
 		}],
+		["testp"] => [{
+			"balance" => BigDecimal(1234),
+			"plan_name" => "test_usd",
+			"expires_at" => Time.now + 100,
+			"parent_customer_id" => "1234"
+		}],
 		["test_v2"] => [{
 			"balance" => BigDecimal(2345),
 			"plan_name" => "test_usd",
@@ -157,23 +165,47 @@ class CustomerRepoTest < Minitest::Test
 		braintree_customer.expect(
 			:create,
 			EMPromise.resolve(
-				OpenStruct.new(success?: true, customer: OpenStruct.new(id: "test"))
+				OpenStruct.new(success?: true, customer: OpenStruct.new(id: "testp"))
 			)
 		)
 		redis.expect(
 			:msetnx,
 			EMPromise.resolve(1),
 			[
-				"jmp_customer_id-test@parented.example.com", "test",
-				"jmp_customer_jid-test", "test@parented.example.com"
+				"jmp_customer_id-test@parented.example.com", "testp",
+				"jmp_customer_jid-testp", "test@parented.example.com"
+			]
+		)
+		redis.expect(
+			:get,
+			EMPromise.resolve("test@parented.example.com"),
+			["jmp_customer_jid-testp"]
+		)
+		redis.expect(
+			:mget,
+			EMPromise.resolve([nil, nil]),
+			[
+				"jmp_customer_auto_top_up_amount-testp",
+				"jmp_customer_monthly_overage_limit-testp"
 			]
 		)
+		redis.expect(
+			:smembers,
+			EMPromise.resolve([]),
+			["jmp_customer_feature_flags-testp"]
+		)
+		CustomerPlan::DB.expect(
+			:exec_defer,
+			EMPromise.resolve(nil),
+			[String, ["testp", "test_usd", "1234"]]
+		)
 		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
+		assert_mock CustomerPlan::DB
 	end
 	em :test_create_parented