1# frozen_string_literal: true
2
3require "multibases"
4require "securerandom"
5
6require_relative "customer"
7require_relative "trust_level_repo"
8
9class ParentCodeRepo
10 def initialize(
11 redis: REDIS,
12 db: DB,
13 trust_level_repo: TrustLevelRepo.new(redis: redis, db: db)
14 )
15 @redis = redis
16 @db = db
17 @trust_level_repo = trust_level_repo
18 end
19
20 def find(code)
21 @redis.hget("jmp_parent_codes", code).then do |parent_id|
22 trust_level_guard(parent_id).then { parent_id }
23 end
24 end
25
26 def find_or_create(customer_id)
27 @redis.get("jmp_customer_parent_code-#{customer_id}").then do |code|
28 next code if code
29
30 code = "p#{Multibases.pack('base32upper', SecureRandom.bytes(4))}"
31 EMPromise.all([
32 @redis.set("jmp_customer_parent_code-#{customer_id}", code),
33 @redis.hset("jmp_parent_codes", code, customer_id)
34 ]).then { code }
35 end
36 end
37
38 def existing_subaccounts(parent_id)
39 @db.query_one(<<~SQL, parent_id, default: { c: 0 }).then { |r| r[:c] }
40 SELECT COUNT(*) AS c FROM customer_plans WHERE parent_customer_id=$1
41 SQL
42 end
43
44 def trust_level_guard(parent_id)
45 return unless parent_id
46
47 @trust_level_repo.find(Customer.new(parent_id, "")).then { |tl|
48 existing_subaccounts(parent_id).then { |c| [tl, c] }
49 }.then do |(tl, number_of_subaccounts)|
50 unless tl.create_subaccount?(number_of_subaccounts)
51 raise "Please contact support to create a subaccount"
52 end
53 end
54 end
55end