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 find_inner(customer_id, jid)
28 end
29 end
30
31 def find_by_jid(jid)
32 if jid.to_s =~ /\Acustomer_(.+)@#{CONFIG[:component][:jid]}\Z/
33 find($1)
34 else
35 @redis.get("jmp_customer_id-#{jid}").then do |customer_id|
36 next find_legacy_customer(jid) unless customer_id
37 find_inner(customer_id, 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 NotFound, "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
62 def put_lidb_name(customer, lidb_name)
63 BandwidthIris::Lidb.create(
64 customer_order_id: customer.customer_id,
65 lidb_tn_groups: { lidb_tn_group: {
66 telephone_numbers: [customer.registered?.phone.sub(/\A\+1/, "")],
67 subscriber_information: lidb_name,
68 use_type: "RESIDENTIAL",
69 visibility: "PUBLIC"
70 } }
71 )
72 end
73
74 def put_transcription_enabled(customer, transcription_enabled)
75 @sgx_repo.put_transcription_enabled(
76 customer.customer_id, transcription_enabled
77 )
78 end
79
80 def put_fwd(customer, customer_fwd)
81 @sgx_repo.put_fwd(
82 customer.customer_id,
83 customer.registered?.phone,
84 customer_fwd
85 )
86 end
87
88protected
89
90 def new_sgx(customer_id)
91 TrivialBackendSgxRepo.new.get(customer_id).with(registered?: false)
92 end
93
94 def find_legacy_customer(jid)
95 @redis.lindex("catapult_cred-#{jid}", 3).then do |tel|
96 raise NotFound, "No customer" unless tel
97 LegacyCustomer.new(Blather::JID.new(jid), tel)
98 end
99 end
100
101 def hydrate_plan(customer_id, raw_customer)
102 raw_customer.dup.tap do |data|
103 data[:plan] = CustomerPlan.new(
104 customer_id,
105 plan: data.delete(:plan_name)&.then(&Plan.method(:for)),
106 expires_at: data.delete(:expires_at)
107 )
108 end
109 end
110
111 def find_inner(customer_id, jid)
112 result = @db.query_defer(<<~SQL, [customer_id])
113 SELECT COALESCE(balance,0) AS balance, plan_name, expires_at
114 FROM customer_plans LEFT JOIN balances USING (customer_id)
115 WHERE customer_id=$1 LIMIT 1
116 SQL
117 EMPromise.all([@sgx_repo.get(customer_id), result]).then do |(sgx, rows)|
118 data = hydrate_plan(customer_id, rows.first&.transform_keys(&:to_sym) || {})
119 Customer.new(customer_id, Blather::JID.new(jid), sgx: sgx, **data)
120 end
121 end
122end