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_delegator :@usage, :report, :usage_report
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)
.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