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 @payment_methods ||=
78 BRAINTREE
79 .customer
80 .find(@customer_id)
81 .then(PaymentMethods.method(:for_braintree_customer))
82 end
83
84 protected def_delegator :@plan, :expires_at
85end