1# frozen_string_literal: true
2
3require "lazy_object"
4
5require_relative "customer"
6require_relative "legacy_customer"
7require_relative "polyfill"
8
9class CustomerRepo
10 class NotFound < RuntimeError; end
11
12 def initialize(
13 redis: LazyObject.new { REDIS },
14 db: LazyObject.new { DB },
15 braintree: LazyObject.new { BRAINTREE },
16 sgx_repo: TrivialBackendSgxRepo.new
17 )
18 @redis = redis
19 @db = db
20 @braintree = braintree
21 @sgx_repo = sgx_repo
22 end
23
24 def find(customer_id)
25 @redis.get("jmp_customer_jid-#{customer_id}").then do |jid|
26 raise NotFound, "No jid" unless jid
27
28 find_inner(customer_id, jid)
29 end
30 end
31
32 def find_by_jid(jid)
33 if jid.to_s =~ /\Acustomer_(.+)@#{CONFIG[:component][:jid]}\Z/
34 find($1)
35 else
36 @redis.get("jmp_customer_id-#{jid}").then do |customer_id|
37 next find_legacy_customer(jid) unless customer_id
38
39 find_inner(customer_id, jid)
40 end
41 end
42 end
43
44 def find_by_tel(tel)
45 @redis.get("catapult_jid-#{tel}").then do |jid|
46 raise NotFound, "No jid" unless jid
47
48 find_by_jid(jid)
49 end
50 end
51
52 def create(jid)
53 @braintree.customer.create.then do |result|
54 raise "Braintree customer create failed" unless result.success?
55
56 cid = result.customer.id
57 @redis.msetnx(
58 "jmp_customer_id-#{jid}", cid, "jmp_customer_jid-#{cid}", jid
59 ).then do |redis_result|
60 raise "Saving new customer to redis failed" unless redis_result == 1
61
62 Customer.new(cid, Blather::JID.new(jid), sgx: new_sgx(cid))
63 end
64 end
65 end
66
67 def put_lidb_name(customer, lidb_name)
68 BandwidthIris::Lidb.create(
69 customer_order_id: customer.customer_id,
70 lidb_tn_groups: { lidb_tn_group: {
71 telephone_numbers: [customer.registered?.phone.sub(/\A\+1/, "")],
72 subscriber_information: lidb_name,
73 use_type: "RESIDENTIAL", visibility: "PUBLIC"
74 } }
75 )
76 end
77
78 def put_transcription_enabled(customer, transcription_enabled)
79 @sgx_repo.put_transcription_enabled(
80 customer.customer_id, transcription_enabled
81 )
82 end
83
84 def put_fwd(customer, customer_fwd)
85 @sgx_repo.put_fwd(
86 customer.customer_id, customer.registered?.phone, customer_fwd
87 )
88 end
89
90protected
91
92 def new_sgx(customer_id)
93 TrivialBackendSgxRepo.new.get(customer_id).with(registered?: false)
94 end
95
96 def find_legacy_customer(jid)
97 @redis.lindex("catapult_cred-#{jid}", 3).then do |tel|
98 raise NotFound, "No customer" unless tel
99
100 LegacyCustomer.new(Blather::JID.new(jid), tel)
101 end
102 end
103
104 def hydrate_plan(customer_id, raw_customer)
105 raw_customer.dup.tap do |data|
106 data[:plan] = CustomerPlan.new(
107 customer_id,
108 plan: data.delete(:plan_name)&.then(&Plan.method(:for)),
109 expires_at: data.delete(:expires_at)
110 )
111 end
112 end
113
114 SQL = <<~SQL
115 SELECT COALESCE(balance,0) AS balance, plan_name, expires_at
116 FROM customer_plans LEFT JOIN balances USING (customer_id)
117 WHERE customer_id=$1 LIMIT 1
118 SQL
119
120 def find_inner(customer_id, jid)
121 result = @db.query_defer(SQL, [customer_id])
122 EMPromise.all([@sgx_repo.get(customer_id), result]).then do |(sgx, rows)|
123 data = hydrate_plan(
124 customer_id,
125 rows.first&.transform_keys(&:to_sym) || {}
126 )
127 Customer.new(customer_id, Blather::JID.new(jid), sgx: sgx, **data)
128 end
129 end
130end