customer.rb

  1# frozen_string_literal: true
  2
  3require "forwardable"
  4
  5require_relative "./blather_ext"
  6require_relative "./customer_usage"
  7require_relative "./customer_plan"
  8require_relative "./customer_ogm"
  9require_relative "./customer_financials"
 10require_relative "./backend_sgx"
 11require_relative "./invites_repo"
 12require_relative "./payment_methods"
 13require_relative "./plan"
 14require_relative "./proxied_jid"
 15require_relative "./sip_account"
 16require_relative "./trivial_backend_sgx_repo"
 17
 18class Customer
 19	extend Forwardable
 20
 21	attr_reader :customer_id, :balance, :jid, :tndetails, :feature_flags
 22	alias billing_customer_id customer_id
 23
 24	def_delegators :@plan, :active?, :activate_plan_starting_now, :bill_plan,
 25	               :currency, :merchant_account, :plan_name, :minute_limit,
 26	               :message_limit, :monthly_overage_limit, :activation_date,
 27	               :expires_at, :monthly_price, :save_plan!, :auto_top_up_amount,
 28	               :extend_plan, :status
 29	def_delegators :@sgx, :deregister!, :register!, :registered?, :set_ogm_url,
 30	               :fwd, :transcription_enabled, :set_port_out_pin, :tn_portable?
 31	def_delegators :@usage, :usage_report, :message_usage, :incr_message_usage,
 32	               :calling_charges_this_month
 33	def_delegators :@financials, :payment_methods, :declines, :mark_decline,
 34	               :btc_addresses, :add_btc_address, :transactions,
 35	               :bch_addresses, :add_bch_address
 36
 37	def self.extract(customer_id, jid, **kwargs)
 38		(kwargs[:parent_customer_id] ? ChildCustomer : Customer).new(
 39			customer_id, jid,
 40			plan: CustomerPlan.extract(customer_id: customer_id, **kwargs),
 41			**kwargs.slice(:balance, :sgx, :tndetails, :feature_flags)
 42		)
 43	end
 44
 45	def self.created(customer_id, jid, repo:, **kwargs)
 46		jid = Blather::JID.new(jid)
 47		plan = CustomerPlan.default(customer_id, jid)
 48		if plan.parent_customer_id
 49			# Parent may have a balance, so look it up
 50			plan.save_plan!.then { repo.find(customer_id) }
 51		else
 52			new(customer_id, jid, plan: plan, **kwargs)
 53		end
 54	end
 55
 56	def initialize(
 57		customer_id,
 58		jid,
 59		sgx:,
 60		plan: CustomerPlan.new(customer_id),
 61		balance: BigDecimal(0),
 62		tndetails: {},
 63		feature_flags: []
 64	)
 65		@plan = plan
 66		@usage = CustomerUsage.new(customer_id)
 67		@financials = CustomerFinancials.new(customer_id)
 68		@customer_id = customer_id
 69		@jid = jid
 70		@balance = balance
 71		@tndetails = tndetails
 72		@feature_flags = feature_flags
 73		@sgx = sgx
 74	end
 75
 76	def with_balance(balance)
 77		self.class.new(
 78			@customer_id, @jid,
 79			plan: @plan, balance: balance,
 80			tndetails: @tndetails, sgx: @sgx
 81		)
 82	end
 83
 84	def with_plan(plan_name, **kwargs)
 85		self.class.new(
 86			@customer_id, @jid,
 87			plan: @plan.with(plan_name: plan_name, **kwargs),
 88			balance: @balance, tndetails: @tndetails, sgx: @sgx
 89		)
 90	end
 91
 92	def billing_customer(*)
 93		EMPromise.resolve(self)
 94	end
 95
 96	def stanza_to(stanza)
 97		stanza = stanza.dup
 98		stanza.to = jid.with(resource: stanza.to&.resource)
 99		stanza.from ||= Blather::JID.new("")
100		stanza.from = stanza.from.with(domain: CONFIG[:component][:jid])
101		block_given? ? yield(stanza) : (BLATHER << stanza)
102	end
103
104	def stanza_from(stanza)
105		BLATHER << @sgx.stanza(stanza)
106	end
107
108	def fetch_pep(node, from_tel=nil)
109		from_tel = nil unless from_tel.to_s.start_with?("+")
110		iq = Blather::Stanza::PubSub::Items.new(:get)
111		iq.node = node
112		iq.from = Blather::JID.new(from_tel, CONFIG[:component][:jid])
113		stanza_to(iq, &IQ_MANAGER.method(:write))
114	end
115
116	def ogm(from_tel=nil)
117		fetch_vcard = -> { fetch_pep("urn:xmpp:vcard4", from_tel) }
118		CustomerOGM.for(@sgx.ogm_url, @sgx.registered?.phone, fetch_vcard)
119	end
120
121	def sip_account
122		SipAccount.find(customer_id)
123	end
124
125	def sgx
126		@sgx.jid
127	end
128
129	def reset_sip_account
130		sip_account.with_random_password.put
131	end
132
133	def admin?
134		CONFIG[:admins].include?(jid.to_s)
135	end
136
137	class ChildCustomer < Customer
138		def billing_customer_id
139			@plan.parent_customer_id
140		end
141
142		def billing_customer(repo=CustomerRepo.new)
143			repo.find(billing_customer_id)
144		end
145	end
146end