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			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