customer_repo.rb

  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