~singpolyma/sgx-jmp

ref: b9c4c2cb0cfdb321c351c826c2b8ed5655088e12 sgx-jmp/lib/customer.rb -rw-r--r-- 3.1 KiB
b9c4c2cbStephen Paul Weber Notify admin if a user goes over 500 messages in 30 days 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# frozen_string_literal: true

require "forwardable"

require_relative "./blather_ext"
require_relative "./customer_plan"
require_relative "./customer_usage"
require_relative "./backend_sgx"
require_relative "./ibr"
require_relative "./payment_methods"
require_relative "./plan"
require_relative "./sip_account"

class Customer
	def self.for_jid(jid)
		REDIS.get("jmp_customer_id-#{jid}").then do |customer_id|
			raise "No customer id" unless customer_id
			for_customer_id(customer_id)
		end
	end

	def self.for_customer_id(customer_id)
		result = DB.query_defer(<<~SQL, [customer_id])
			SELECT COALESCE(balance,0) AS balance, plan_name, expires_at
			FROM customer_plans LEFT JOIN balances USING (customer_id)
			WHERE customer_id=$1 LIMIT 1
		SQL
		result.then do |rows|
			new(customer_id, **rows.first&.transform_keys(&:to_sym) || {})
		end
	end

	def self.create(jid)
		BRAINTREE.customer.create.then do |result|
			raise "Braintree customer create failed" unless result.success?
			cid = result.customer.id
			REDIS.msetnx(
				"jmp_customer_id-#{jid}", cid, "jmp_customer_jid-#{cid}", jid
			).then do |redis_result|
				raise "Saving new customer to redis failed" unless redis_result == 1
				new(cid)
			end
		end
	end

	extend Forwardable

	attr_reader :customer_id, :balance
	def_delegators :@plan, :active?, :activate_plan_starting_now, :bill_plan,
	               :currency, :merchant_account, :plan_name
	def_delegators :@sgx, :register!, :registered?
	def_delegators :@usage, :usage_report, :message_usage, :incr_message_usage

	def initialize(
		customer_id,
		plan_name: nil,
		expires_at: Time.now,
		balance: BigDecimal.new(0),
		sgx: BackendSgx.new(customer_id)
	)
		@plan = CustomerPlan.new(
			customer_id,
			plan: plan_name && Plan.for(plan_name), expires_at: expires_at
		)
		@usage = CustomerUsage.new(customer_id)
		@customer_id = customer_id
		@balance = balance
		@sgx = sgx
	end

	def with_plan(plan_name)
		self.class.new(
			@customer_id,
			balance: @balance,
			expires_at: expires_at,
			plan_name: plan_name
		)
	end

	def payment_methods
		BRAINTREE
			.customer
			.find(@customer_id)
			.catch { OpenStruct.new(payment_methods: []) }
			.then(PaymentMethods.method(:for_braintree_customer))
	end

	def jid
		@jid ||= REDIS.get("jmp_customer_jid-#{customer_id}").then do |sjid|
			Blather::JID.new(sjid)
		end
	end

	def stanza_to(stanza)
		jid.then do |jid|
			stanza = stanza.dup
			stanza.to = jid.with(resource: stanza.to&.resource)
			stanza.from = stanza.from.with(domain: CONFIG[:component][:jid])
			BLATHER << stanza
		end
	end

	def stanza_from(stanza)
		BLATHER << @sgx.stanza(stanza)
	end

	def sip_account
		SipAccount.find(customer_id)
	end

	def reset_sip_account
		SipAccount::New.new(username: customer_id).put.catch do
			sip_account.then { |acct| acct.with_random_password.put }
		end
	end

	def btc_addresses
		REDIS.smembers("jmp_customer_btc_addresses-#{customer_id}")
	end

	def add_btc_address
		ELECTRUM.createnewaddress.then do |addr|
			REDIS.sadd("jmp_customer_btc_addresses-#{customer_id}", addr).then do
				addr
			end
		end
	end

	protected def_delegator :@plan, :expires_at
end