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