1# frozen_string_literal: true
2
3require "lazy_object"
4
5require_relative "customer"
6require_relative "legacy_customer"
7require_relative "polyfill"
8
9class CustomerRepo
10 def initialize(
11 redis: LazyObject.new { REDIS },
12 db: LazyObject.new { DB },
13 braintree: LazyObject.new { BRAINTREE },
14 sgx_repo: TrivialBackendSgxRepo.new
15 )
16 @redis = redis
17 @db = db
18 @braintree = braintree
19 @sgx_repo = sgx_repo
20 end
21
22 def find(customer_id)
23 @redis.get("jmp_customer_jid-#{customer_id}").then do |jid|
24 raise "No jid" unless jid
25 find_inner(customer_id, jid)
26 end
27 end
28
29 def find_by_jid(jid)
30 if jid.to_s =~ /\Acustomer_(.+)@#{CONFIG[:component][:jid]}\Z/
31 find($1)
32 else
33 @redis.get("jmp_customer_id-#{jid}").then { |customer_id|
34 raise "No customer id" unless customer_id
35 find_inner(customer_id, jid)
36 }.catch do
37 find_legacy_customer(jid)
38 end
39 end
40 end
41
42 def find_by_tel(tel)
43 @redis.get("catapult_jid-#{tel}").then do |jid|
44 raise "No jid" unless jid
45 find_by_jid(jid)
46 end
47 end
48
49 def create(jid)
50 @braintree.customer.create.then do |result|
51 raise "Braintree customer create failed" unless result.success?
52 cid = result.customer.id
53 @redis.msetnx(
54 "jmp_customer_id-#{jid}", cid, "jmp_customer_jid-#{cid}", jid
55 ).then do |redis_result|
56 raise "Saving new customer to redis failed" unless redis_result == 1
57 Customer.new(cid, Blather::JID.new(jid), sgx: new_sgx(cid))
58 end
59 end
60 end
61
62protected
63
64 def new_sgx(customer_id)
65 TrivialBackendSgxRepo.new.get(customer_id).with(
66 registered?: false
67 )
68 end
69
70 def find_legacy_customer(jid)
71 @redis.lindex("catapult_cred-#{jid}", 3).then do |tel|
72 raise "No customer" unless tel
73 LegacyCustomer.new(Blather::JID.new(jid), tel)
74 end
75 end
76
77 def hydrate_plan(customer_id, raw_customer)
78 raw_customer.dup.tap do |data|
79 data[:plan] = CustomerPlan.new(
80 customer_id,
81 plan: data.delete(:plan_name)&.then(&Plan.method(:for)),
82 expires_at: data.delete(:expires_at)
83 )
84 end
85 end
86
87 def find_inner(customer_id, jid)
88 result = @db.query_defer(<<~SQL, [customer_id])
89 SELECT COALESCE(balance,0) AS balance, plan_name, expires_at
90 FROM customer_plans LEFT JOIN balances USING (customer_id)
91 WHERE customer_id=$1 LIMIT 1
92 SQL
93 EMPromise.all([@sgx_repo.get(customer_id), result]).then do |(sgx, rows)|
94 data = hydrate_plan(customer_id, rows.first&.transform_keys(&:to_sym) || {})
95 Customer.new(customer_id, Blather::JID.new(jid), sgx: sgx, **data)
96 end
97 end
98end