customer_financials.rb

 1# frozen_string_literal: true
 2
 3require "bigdecimal"
 4
 5class CustomerFinancials
 6	def initialize(customer_id)
 7		@customer_id = customer_id
 8	end
 9
10	def payment_methods
11		EMPromise.all([
12			BRAINTREE
13				.customer
14				.find(@customer_id)
15				.catch { OpenStruct.new(payment_methods: []) },
16			REDIS.smembers("block_credit_cards")
17		]).then { |(braintree, badcards)| PaymentMethods.for(braintree, badcards) }
18	end
19
20	def btc_addresses
21		REDIS.smembers("jmp_customer_btc_addresses-#{@customer_id}")
22	end
23
24	def add_btc_address
25		REDIS.spopsadd([
26			"jmp_available_btc_addresses",
27			"jmp_customer_btc_addresses-#{@customer_id}"
28		]).then do |addr|
29			ELECTRUM.notify(
30				addr,
31				CONFIG[:electrum_notify_url].call(addr, @customer_id)
32			)
33			addr
34		end
35	end
36
37	def declines
38		REDIS.get("jmp_pay_decline-#{@customer_id}").then(&:to_i)
39	end
40
41	def mark_decline
42		REDIS.incr("jmp_pay_decline-#{@customer_id}").then do
43			REDIS.expire("jmp_pay_decline-#{@customer_id}", 60 * 60 * 24)
44		end
45	end
46
47	def set_declines(num)
48		if num.positive?
49			REDIS.set("jmp_pay_decline-#{@customer_id}", num)
50		else
51			REDIS.del("jmp_pay_decline-#{@customer_id}")
52		end
53	end
54
55	class TransactionInfo
56		value_semantics do
57			transaction_id String
58			created_at Time
59			amount BigDecimal
60			note String, coerce: ->(x) { x || "" }
61		end
62
63		def formatted_amount
64			"$%.4f" % amount
65		end
66	end
67
68	TRANSACTIONS_SQL = <<~SQL
69		SELECT
70			transaction_id,
71			created_at,
72			amount,
73			note
74		FROM transactions
75		WHERE customer_id = $1
76		ORDER BY created_at;
77	SQL
78
79	def transactions
80		txns = DB.query_defer(TRANSACTIONS_SQL, [@customer_id])
81
82		txns.then do |rows|
83			rows.map { |row|
84				TransactionInfo.new(**row.transform_keys(&:to_sym))
85			}
86		end
87	end
88end