low_balance.rb

 1# frozen_string_literal: true
 2
 3require_relative "expiring_lock"
 4require_relative "transaction"
 5
 6class LowBalance
 7	def self.for(customer)
 8		return Locked.new unless customer.registered?
 9
10		ExpiringLock.new(
11			"jmp_customer_low_balance-#{customer.customer_id}",
12			expiry: 60 * 60 * 24 * 7
13		).with(-> { Locked.new }) do
14			customer.auto_top_up_amount.then do |auto_top_up_amount|
15				for_auto_top_up_amount(customer, auto_top_up_amount)
16			end
17		end
18	end
19
20	def self.for_auto_top_up_amount(customer, auto_top_up_amount)
21		if auto_top_up_amount.positive?
22			AutoTopUp.new(customer, auto_top_up_amount)
23		else
24			customer.btc_addresses.then do |btc_addresses|
25				new(customer, btc_addresses)
26			end
27		end
28	end
29
30	def initialize(customer, btc_addresses)
31		@customer = customer
32		@btc_addresses = btc_addresses
33	end
34
35	def notify!
36		m = Blather::Stanza::Message.new
37		m.from = CONFIG[:notify_from]
38		m.body =
39			"Your balance of $#{'%.4f' % @customer.balance} is low." \
40			"#{btc_addresses_for_notification}"
41		@customer.stanza_to(m)
42	end
43
44	def btc_addresses_for_notification
45		return if @btc_addresses.empty?
46
47		"\nYou can buy credit by sending any amount of Bitcoin to one of " \
48		"these addresses:\n#{@btc_addresses.join("\n")}"
49	end
50
51	class AutoTopUp
52		def initialize(customer, auto_top_up_amount)
53			@customer = customer
54			@auto_top_up_amount = auto_top_up_amount
55			@message = Blather::Stanza::Message.new
56			@message.from = CONFIG[:notify_from]
57		end
58
59		def sale
60			Transaction.sale(@customer, amount: @auto_top_up_amount).then do |tx|
61				tx.insert.then { tx }
62			end
63		end
64
65		def notify!
66			sale.then { |tx|
67				@message.body =
68					"Automatic top-up has charged your default " \
69					"payment method and added #{tx} to your balance."
70			}.catch { |e|
71				@message.body =
72					"Automatic top-up transaction for " \
73					"$#{@auto_top_up_amount} failed: #{e.message}"
74			}.then { @customer.stanza_to(@message) }
75		end
76	end
77
78	class Locked
79		def notify!; end
80	end
81end