M lib/customer.rb => lib/customer.rb +10 -56
@@ 2,6 2,7 @@
require "forwardable"
+require_relative "./customer_plan"
require_relative "./backend_sgx"
require_relative "./ibr"
require_relative "./payment_methods"
@@ 29,8 30,8 @@ class Customer
extend Forwardable
attr_reader :customer_id, :balance
- def_delegator :@plan, :name, :plan_name
- def_delegators :@plan, :currency, :merchant_account
+ def_delegators :@plan, :active?, :activate_plan_starting_now, :bill_plan,
+ :currency, :merchant_account, :plan_name
def_delegators :@sgx, :register!, :registered?
def initialize(
@@ 40,8 41,11 @@ class Customer
balance: BigDecimal.new(0),
sgx: BackendSgx.new(customer_id)
)
- @plan = plan_name && Plan.for(plan_name)
- @expires_at = expires_at
+ @plan = CustomerPlan.new(
+ customer_id,
+ plan: plan_name && Plan.for(plan_name),
+ expires_at: expires_at
+ )
@customer_id = customer_id
@balance = balance
@sgx = sgx
@@ 51,29 55,11 @@ class Customer
self.class.new(
@customer_id,
balance: @balance,
- expires_at: @expires_at,
+ expires_at: expires_at,
plan_name: plan_name
)
end
- def bill_plan
- EM.promise_fiber do
- DB.transaction do
- charge_for_plan
- add_one_month_to_current_plan unless activate_plan_starting_now
- end
- end
- end
-
- def activate_plan_starting_now
- DB.exec(<<~SQL, [@customer_id, plan_name]).cmd_tuples.positive?
- INSERT INTO plan_log
- (customer_id, plan_name, date_range)
- VALUES ($1, $2, tsrange(LOCALTIMESTAMP, LOCALTIMESTAMP + '1 month'))
- ON CONFLICT DO NOTHING
- SQL
- end
-
def payment_methods
@payment_methods ||=
BRAINTREE
@@ 82,37 68,5 @@ class Customer
.then(PaymentMethods.method(:for_braintree_customer))
end
- def active?
- @plan && @expires_at > Time.now
- end
-
-protected
-
- def charge_for_plan
- params = [
- @customer_id,
- "#{@customer_id}-bill-#{plan_name}-at-#{Time.now.to_i}",
- -@plan.monthly_price
- ]
- DB.exec(<<~SQL, params)
- INSERT INTO transactions
- (customer_id, transaction_id, created_at, amount)
- VALUES ($1, $2, LOCALTIMESTAMP, $3)
- SQL
- end
-
- def add_one_month_to_current_plan
- DB.exec(<<~SQL, [@customer_id])
- UPDATE plan_log SET date_range=range_merge(
- date_range,
- tsrange(
- LOCALTIMESTAMP,
- GREATEST(upper(date_range), LOCALTIMESTAMP) + '1 month'
- )
- )
- WHERE
- customer_id=$1 AND
- date_range && tsrange(LOCALTIMESTAMP, LOCALTIMESTAMP + '1 month')
- SQL
- end
+ protected def_delegator :@plan, :expires_at
end
A lib/customer_plan.rb => lib/customer_plan.rb +69 -0
@@ 0,0 1,69 @@
+# frozen_string_literal: true
+
+require "forwardable"
+
+class CustomerPlan
+ extend Forwardable
+
+ attr_reader :expires_at
+ def_delegator :@plan, :name, :plan_name
+ def_delegators :@plan, :currency, :merchant_account
+
+ def initialize(customer_id, plan: nil, expires_at: Time.now)
+ @customer_id = customer_id
+ @plan = plan
+ @expires_at = expires_at
+ end
+
+ def active?
+ @plan && @expires_at > Time.now
+ end
+
+ def bill_plan
+ EM.promise_fiber do
+ DB.transaction do
+ charge_for_plan
+ add_one_month_to_current_plan unless activate_plan_starting_now
+ end
+ end
+ end
+
+ def activate_plan_starting_now
+ DB.exec(<<~SQL, [@customer_id, plan_name]).cmd_tuples.positive?
+ INSERT INTO plan_log
+ (customer_id, plan_name, date_range)
+ VALUES ($1, $2, tsrange(LOCALTIMESTAMP, LOCALTIMESTAMP + '1 month'))
+ ON CONFLICT DO NOTHING
+ SQL
+ end
+
+protected
+
+ def charge_for_plan
+ params = [
+ @customer_id,
+ "#{@customer_id}-bill-#{plan_name}-at-#{Time.now.to_i}",
+ -@plan.monthly_price
+ ]
+ DB.exec(<<~SQL, params)
+ INSERT INTO transactions
+ (customer_id, transaction_id, created_at, amount)
+ VALUES ($1, $2, LOCALTIMESTAMP, $3)
+ SQL
+ end
+
+ def add_one_month_to_current_plan
+ DB.exec(<<~SQL, [@customer_id])
+ UPDATE plan_log SET date_range=range_merge(
+ date_range,
+ tsrange(
+ LOCALTIMESTAMP,
+ GREATEST(upper(date_range), LOCALTIMESTAMP) + '1 month'
+ )
+ )
+ WHERE
+ customer_id=$1 AND
+ date_range && tsrange(LOCALTIMESTAMP, LOCALTIMESTAMP + '1 month')
+ SQL
+ end
+end
M test/test_customer.rb => test/test_customer.rb +10 -9
@@ 5,6 5,7 @@ require "customer"
Customer::REDIS = Minitest::Mock.new
Customer::DB = Minitest::Mock.new
+CustomerPlan::DB = Minitest::Mock.new
class CustomerTest < Minitest::Test
def test_for_jid
@@ 49,11 50,11 @@ class CustomerTest < Minitest::Test
em :test_for_customer_id_not_found
def test_bill_plan_activate
- Customer::DB.expect(:transaction, nil) do |&block|
+ CustomerPlan::DB.expect(:transaction, nil) do |&block|
block.call
true
end
- Customer::DB.expect(
+ CustomerPlan::DB.expect(
:exec,
nil,
[
@@ 65,22 66,22 @@ class CustomerTest < Minitest::Test
end
]
)
- Customer::DB.expect(
+ CustomerPlan::DB.expect(
:exec,
OpenStruct.new(cmd_tuples: 1),
[String, ["test", "test_usd"]]
)
Customer.new("test", plan_name: "test_usd").bill_plan.sync
- Customer::DB.verify
+ CustomerPlan::DB.verify
end
em :test_bill_plan_activate
def test_bill_plan_update
- Customer::DB.expect(:transaction, nil) do |&block|
+ CustomerPlan::DB.expect(:transaction, nil) do |&block|
block.call
true
end
- Customer::DB.expect(
+ CustomerPlan::DB.expect(
:exec,
nil,
[
@@ 92,14 93,14 @@ class CustomerTest < Minitest::Test
end
]
)
- Customer::DB.expect(
+ CustomerPlan::DB.expect(
:exec,
OpenStruct.new(cmd_tuples: 0),
[String, ["test", "test_usd"]]
)
- Customer::DB.expect(:exec, nil, [String, ["test"]])
+ CustomerPlan::DB.expect(:exec, nil, [String, ["test"]])
Customer.new("test", plan_name: "test_usd").bill_plan.sync
- Customer::DB.verify
+ CustomerPlan::DB.verify
end
em :test_bill_plan_update
end