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			for_auto_top_up_amount(customer)
15		end
16	end
17
18	def self.for_auto_top_up_amount(customer)
19		if customer.auto_top_up_amount.positive?
20			AutoTopUp.new(customer)
21		else
22			customer.btc_addresses.then do |btc_addresses|
23				new(customer, btc_addresses)
24			end
25		end
26	end
27
28	def initialize(customer, btc_addresses)
29		@customer = customer
30		@btc_addresses = btc_addresses
31	end
32
33	def notify!
34		m = Blather::Stanza::Message.new
35		m.from = CONFIG[:notify_from]
36		m.body =
37			"Your balance of $#{'%.4f' % @customer.balance} is low." \
38			"#{btc_addresses_for_notification}"
39		@customer.stanza_to(m)
40		EMPromise.resolve(0)
41	end
42
43	def btc_addresses_for_notification
44		return if @btc_addresses.empty?
45
46		"\nYou can buy credit by sending any amount of Bitcoin to one of " \
47		"these addresses:\n#{@btc_addresses.join("\n")}"
48	end
49
50	class AutoTopUp
51		def initialize(customer)
52			@customer = customer
53			@message = Blather::Stanza::Message.new
54			@message.from = CONFIG[:notify_from]
55		end
56
57		def sale
58			Transaction.sale(
59				@customer,
60				amount: @customer.auto_top_up_amount
61			).then do |tx|
62				tx.insert.then { tx }
63			end
64		end
65
66		def failed(e)
67			@message.body =
68				"Automatic top-up transaction for " \
69				"$#{@customer.auto_top_up_amount} failed: #{e.message}"
70			0
71		end
72
73		def notify!
74			sale.then { |tx|
75				@message.body =
76					"Automatic top-up has charged your default " \
77					"payment method and added #{tx} to your balance."
78				tx.total
79			}.catch(&method(:failed)).then { |amount|
80				@customer.stanza_to(@message)
81				amount
82			}
83		end
84	end
85
86	class Locked
87		def notify!
88			EMPromise.resolve(0)
89		end
90	end
91end