customer.rb

  1# frozen_string_literal: true
  2
  3require "forwardable"
  4
  5require_relative "./blather_ext"
  6require_relative "./customer_plan"
  7require_relative "./backend_sgx"
  8require_relative "./ibr"
  9require_relative "./payment_methods"
 10require_relative "./plan"
 11
 12class Customer
 13	def self.for_jid(jid)
 14		REDIS.get("jmp_customer_id-#{jid}").then do |customer_id|
 15			raise "No customer id" unless customer_id
 16			for_customer_id(customer_id)
 17		end
 18	end
 19
 20	def self.for_customer_id(customer_id)
 21		result = DB.query_defer(<<~SQL, [customer_id])
 22			SELECT COALESCE(balance,0) AS balance, plan_name, expires_at
 23			FROM customer_plans LEFT JOIN balances USING (customer_id)
 24			WHERE customer_id=$1 LIMIT 1
 25		SQL
 26		result.then do |rows|
 27			new(customer_id, **rows.first&.transform_keys(&:to_sym) || {})
 28		end
 29	end
 30
 31	def self.create(jid)
 32		BRAINTREE.customer.create.then do |result|
 33			raise "Braintree customer create failed" unless result.success?
 34			cid = result.customer.id
 35			REDIS.msetnx(
 36				"jmp_customer_id-#{jid}", cid, "jmp_customer_jid-#{cid}", jid
 37			).then do |redis_result|
 38				raise "Saving new customer to redis failed" unless redis_result == 1
 39				new(cid)
 40			end
 41		end
 42	end
 43
 44	extend Forwardable
 45
 46	attr_reader :customer_id, :balance
 47	def_delegators :@plan, :active?, :activate_plan_starting_now, :bill_plan,
 48	               :currency, :merchant_account, :plan_name
 49	def_delegators :@sgx, :register!, :registered?
 50
 51	def initialize(
 52		customer_id,
 53		plan_name: nil,
 54		expires_at: Time.now,
 55		balance: BigDecimal.new(0),
 56		sgx: BackendSgx.new(customer_id)
 57	)
 58		@plan = CustomerPlan.new(
 59			customer_id,
 60			plan: plan_name && Plan.for(plan_name),
 61			expires_at: expires_at
 62		)
 63		@customer_id = customer_id
 64		@balance = balance
 65		@sgx = sgx
 66	end
 67
 68	def with_plan(plan_name)
 69		self.class.new(
 70			@customer_id,
 71			balance: @balance,
 72			expires_at: expires_at,
 73			plan_name: plan_name
 74		)
 75	end
 76
 77	def payment_methods
 78		BRAINTREE
 79			.customer
 80			.find(@customer_id)
 81			.then(PaymentMethods.method(:for_braintree_customer))
 82	end
 83
 84	def jid
 85		@jid ||= REDIS.get("jmp_customer_jid-#{customer_id}").then do |sjid|
 86			Blather::JID.new(sjid)
 87		end
 88	end
 89
 90	def stanza_to(stanza)
 91		jid.then do |jid|
 92			stanza = stanza.dup
 93			stanza.to = jid.with(resource: stanza.to&.resource)
 94			stanza.from = stanza.from.with(domain: CONFIG[:component][:jid])
 95			BLATHER << stanza
 96		end
 97	end
 98
 99	def stanza_from(stanza)
100		BLATHER << @sgx.stanza(stanza)
101	end
102
103	protected def_delegator :@plan, :expires_at
104end