@@ 10,7 10,8 @@
# target = \(tel: Text) -> "${tel}@cheogram.com"
# },
# electrum = env:ELECTRUM_CONFIG,
-# plans = ./plans.dhall
+# plans = ./plans.dhall,
+# activation_amount = 10000
# }'
require "bigdecimal"
@@ 63,19 64,36 @@ btc_sell_price[:CAD] = BigDecimal.new(
btc_sell_price[:USD] = btc_sell_price[:CAD] * cad_to_usd
class Plan
- def self.for_customer(customer_id)
- row = DB.exec_params(<<-SQL, [customer_id]).first
+ def self.for_customer(customer)
+ row = DB.exec_params(<<-SQL, [customer.id]).first
SELECT plan_name FROM customer_plans WHERE customer_id=$1 LIMIT 1
SQL
- return unless row
- plan = CONFIG[:plans].find { |p| p["plan_name"] = row["plan_name"] }
- new(plan) if plan
+ from_name(customer, row&.[]("plan_name"))
end
- def initialize(plan)
+ def self.pending_for_customer(customer)
+ from_name(
+ customer,
+ REDIS.get("pending_plan_for-#{customer.id}"),
+ klass: Pending
+ )
+ end
+
+ def self.from_name(customer, plan_name, klass: Plan)
+ return unless plan_name
+ plan = CONFIG[:plans].find { |p| p[:name] == plan_name }
+ klass.new(customer, plan) if plan
+ end
+
+ def initialize(customer, plan)
+ @customer = customer
@plan = plan
end
+ def name
+ @plan[:name]
+ end
+
def currency
@plan[:currency]
end
@@ 84,6 102,60 @@ class Plan
bonus = (0.050167 * fiat_amount) - (currency == :CAD ? 1 : cad_to_usd)
return bonus.round(4, :floor) if bonus > 0
end
+
+ def price
+ BigDecimal.new(@plan[:monthly_price].to_i) * 0.0001
+ end
+
+ def insert(start:, expire:)
+ params = [@customer.id, name, start, expire]
+ DB.exec_params(<<-SQL, params)
+ INSERT INTO plan_log
+ (customer_id, plan_name, starts_at, expires_at)
+ VALUES
+ ($1, $2, $3, $4)
+ SQL
+ end
+
+ def activate_any_pending_plan!; end
+
+ class Pending < Plan
+ def initialize(customer, plan)
+ super
+ @go_until = Date.today >> 1
+ end
+
+ def activation_amount
+ camnt = BigDecimal.new(CONFIG[:activation_amount].to_i) * 0.0001
+ [camnt, price].max
+ end
+
+ def activate_any_pending_plan!
+ if @customer.balance < activation_amount
+ @customer.notify(
+ "Your account could not be activated because your " \
+ "balance of $#{@customer.balance} is less that the " \
+ "required activation amount of $#{activation_amount}. " \
+ "Please buy more credit to have your account activated."
+ )
+ else
+ charge_insert_notify
+ end
+ end
+
+ protected
+
+ def charge_insert_notify
+ @customer.add_transaction(
+ "activate_#{name}_until_#{@go_until}",
+ -price,
+ "Activate pending plan"
+ )
+ insert(start: Date.today, expire: @go_until)
+ REDIS.del("pending_plan_for-#{@customer.id}")
+ # TODO: @customer.notify("Your account has been activated")
+ end
+ end
end
class Customer
@@ 91,6 163,10 @@ class Customer
@customer_id = customer_id
end
+ def id
+ @customer_id
+ end
+
def notify(body)
jid = REDIS.get("jmp_customer_jid-#{@customer_id}")
tel = REDIS.lindex("catapult_cred-#{jid}", 3)
@@ 101,7 177,18 @@ class Customer
end
def plan
- Plan.for_customer(@customer_id)
+ Plan.for_customer(self) || pending_plan
+ end
+
+ def pending_plan
+ Plan.pending_for_customer(self)
+ end
+
+ def balance
+ result = DB.exec_params(<<-SQL, [@customer_id]).first&.[]("balance")
+ SELECT balance FROM balances WHERE customer_id=$1
+ SQL
+ result || BigDecimal.new(0)
end
def add_btc_credit(txid, fiat_amount, cad_to_usd)
@@ 122,8 209,6 @@ class Customer
].compact.join)
end
-protected
-
def add_transaction(id, amount, note)
DB.exec_params(<<-SQL, [@customer_id, id, amount, note])
INSERT INTO transactions
@@ 146,13 231,13 @@ REDIS.hgetall("pending_btc_transactions").each do |(txid, customer_id)|
end
DB.transaction do
customer = Customer.new(customer_id)
- plan = customer.plan
- if plan
+ if (plan = customer.plan)
amount = btc * btc_sell_price.fetch(plan.currency).round(4, :floor)
customer.add_btc_credit(txid, amount, cad_to_usd)
+ customer.plan.activate_any_pending_plan!
+ REDIS.hdel("pending_btc_transactions", txid)
else
warn "No plan for #{customer_id} cannot save #{txid}"
end
end
- REDIS.hdel("pending_btc_transactions", txid)
end