customer.rb

 1# frozen_string_literal: true
 2
 3require "forwardable"
 4
 5require_relative "./customer_plan"
 6require_relative "./backend_sgx"
 7require_relative "./ibr"
 8require_relative "./payment_methods"
 9require_relative "./plan"
10
11class Customer
12	def self.for_jid(jid)
13		REDIS.get("jmp_customer_id-#{jid}").then do |customer_id|
14			raise "No customer id" unless customer_id
15			for_customer_id(customer_id)
16		end
17	end
18
19	def self.for_customer_id(customer_id)
20		result = DB.query_defer(<<~SQL, [customer_id])
21			SELECT COALESCE(balance,0) AS balance, plan_name, expires_at
22			FROM customer_plans LEFT JOIN balances USING (customer_id)
23			WHERE customer_id=$1 LIMIT 1
24		SQL
25		result.then do |rows|
26			new(customer_id, **rows.first&.transform_keys(&:to_sym) || {})
27		end
28	end
29
30	extend Forwardable
31
32	attr_reader :customer_id, :balance
33	def_delegators :@plan, :active?, :activate_plan_starting_now, :bill_plan,
34	               :currency, :merchant_account, :plan_name
35	def_delegators :@sgx, :register!, :registered?
36
37	def initialize(
38		customer_id,
39		plan_name: nil,
40		expires_at: Time.now,
41		balance: BigDecimal.new(0),
42		sgx: BackendSgx.new(customer_id)
43	)
44		@plan = CustomerPlan.new(
45			customer_id,
46			plan: plan_name && Plan.for(plan_name),
47			expires_at: expires_at
48		)
49		@customer_id = customer_id
50		@balance = balance
51		@sgx = sgx
52	end
53
54	def with_plan(plan_name)
55		self.class.new(
56			@customer_id,
57			balance: @balance,
58			expires_at: expires_at,
59			plan_name: plan_name
60		)
61	end
62
63	def payment_methods
64		@payment_methods ||=
65			BRAINTREE
66			.customer
67			.find(@customer_id)
68			.then(PaymentMethods.method(:for_braintree_customer))
69	end
70
71	protected def_delegator :@plan, :expires_at
72end