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	def self.create(jid)
31		BRAINTREE.customer.create.then do |result|
32			raise "Braintree customer create failed" unless result.success?
33			cid = result.customer.id
34			REDIS.msetnx(
35				"jmp_customer_id-#{jid}", cid, "jmp_customer_jid-#{cid}", jid
36			).then do |redis_result|
37				raise "Saving new customer to redis failed" unless redis_result == 1
38				new(cid)
39			end
40		end
41	end
42
43	extend Forwardable
44
45	attr_reader :customer_id, :balance
46	def_delegators :@plan, :active?, :activate_plan_starting_now, :bill_plan,
47	               :currency, :merchant_account, :plan_name
48	def_delegators :@sgx, :register!, :registered?
49
50	def initialize(
51		customer_id,
52		plan_name: nil,
53		expires_at: Time.now,
54		balance: BigDecimal.new(0),
55		sgx: BackendSgx.new(customer_id)
56	)
57		@plan = CustomerPlan.new(
58			customer_id,
59			plan: plan_name && Plan.for(plan_name),
60			expires_at: expires_at
61		)
62		@customer_id = customer_id
63		@balance = balance
64		@sgx = sgx
65	end
66
67	def with_plan(plan_name)
68		self.class.new(
69			@customer_id,
70			balance: @balance,
71			expires_at: expires_at,
72			plan_name: plan_name
73		)
74	end
75
76	def payment_methods
77		BRAINTREE
78			.customer
79			.find(@customer_id)
80			.then(PaymentMethods.method(:for_braintree_customer))
81	end
82
83	protected def_delegator :@plan, :expires_at
84end