1# frozen_string_literal: true
2
3require "forwardable"
4
5class CustomerPlan
6 extend Forwardable
7
8 attr_reader :expires_at
9 def_delegator :@plan, :name, :plan_name
10 def_delegators :@plan, :currency, :merchant_account
11
12 def initialize(customer_id, plan: nil, expires_at: Time.now)
13 @customer_id = customer_id
14 @plan = plan || OpenStruct.new
15 @expires_at = expires_at
16 end
17
18 def active?
19 plan_name && @expires_at > Time.now
20 end
21
22 def auto_top_up_amount
23 REDIS.get("jmp_customer_auto_top_up_amount-#{@customer_id}").then(&:to_i)
24 end
25
26 def bill_plan
27 EM.promise_fiber do
28 DB.transaction do
29 charge_for_plan
30 add_one_month_to_current_plan unless activate_plan_starting_now
31 end
32 end
33 end
34
35 def activate_plan_starting_now
36 DB.exec(<<~SQL, [@customer_id, plan_name]).cmd_tuples.positive?
37 INSERT INTO plan_log
38 (customer_id, plan_name, date_range)
39 VALUES ($1, $2, tsrange(LOCALTIMESTAMP, LOCALTIMESTAMP + '1 month'))
40 ON CONFLICT DO NOTHING
41 SQL
42 end
43
44protected
45
46 def charge_for_plan
47 params = [
48 @customer_id,
49 "#{@customer_id}-bill-#{plan_name}-at-#{Time.now.to_i}",
50 -@plan.monthly_price
51 ]
52 DB.exec(<<~SQL, params)
53 INSERT INTO transactions
54 (customer_id, transaction_id, created_at, amount)
55 VALUES ($1, $2, LOCALTIMESTAMP, $3)
56 SQL
57 end
58
59 def add_one_month_to_current_plan
60 DB.exec(<<~SQL, [@customer_id])
61 UPDATE plan_log SET date_range=range_merge(
62 date_range,
63 tsrange(
64 LOCALTIMESTAMP,
65 GREATEST(upper(date_range), LOCALTIMESTAMP) + '1 month'
66 )
67 )
68 WHERE
69 customer_id=$1 AND
70 date_range && tsrange(LOCALTIMESTAMP, LOCALTIMESTAMP + '1 month')
71 SQL
72 end
73end