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 rescue BandwidthIris::Errors::GenericError
77 raise "Could not set CNAM, please contact support"
78 end
79
80 def put_transcription_enabled(customer, transcription_enabled)
81 @sgx_repo.put_transcription_enabled(
82 customer.customer_id, transcription_enabled
83 )
84 end
85
86 def put_fwd(customer, customer_fwd)
87 tel = customer.registered?.phone
88 @sgx_repo.put_fwd(customer.customer_id, tel, customer_fwd)
89 end
90
91protected
92
93 def new_sgx(customer_id)
94 TrivialBackendSgxRepo.new.get(customer_id).with(registered?: false)
95 end
96
97 def find_legacy_customer(jid)
98 @redis.lindex("catapult_cred-#{jid}", 3).then do |tel|
99 raise NotFound, "No customer" unless tel
100
101 LegacyCustomer.new(Blather::JID.new(jid), tel)
102 end
103 end
104
105 def hydrate_plan(customer_id, raw_customer)
106 raw_customer.dup.tap do |data|
107 data[:plan] = CustomerPlan.new(
108 customer_id,
109 plan: data.delete(:plan_name)&.then(&Plan.method(:for)),
110 expires_at: data.delete(:expires_at)
111 )
112 end
113 end
114
115 SQL = <<~SQL
116 SELECT COALESCE(balance,0) AS balance, plan_name, expires_at
117 FROM customer_plans LEFT JOIN balances USING (customer_id)
118 WHERE customer_id=$1 LIMIT 1
119 SQL
120
121 def find_inner(customer_id, jid)
122 result = @db.query_defer(SQL, [customer_id])
123 EMPromise.all([@sgx_repo.get(customer_id), result]).then do |(sgx, rows)|
124 data = hydrate_plan(
125 customer_id, rows.first&.transform_keys(&:to_sym) || {}
126 )
127 Customer.new(customer_id, Blather::JID.new(jid), sgx: sgx, **data)
128 end
129 end
130end