registration.rb

  1# frozen_string_literal: true
  2
  3require_relative "./oob"
  4
  5class Registration
  6	def self.for(iq, customer, web_register_manager)
  7		raise "TODO" if customer&.active?
  8
  9		EMPromise.resolve(customer&.registered?).then do |registered|
 10			if registered
 11				Registered.new(iq, registered.phone)
 12			else
 13				web_register_manager.choose_tel(iq).then do |(riq, tel)|
 14					Activation.for(riq, customer, tel)
 15				end
 16			end
 17		end
 18	end
 19
 20	class Registered
 21		def initialize(iq, tel)
 22			@reply = iq.reply
 23			@reply.status = :completed
 24			@tel = tel
 25		end
 26
 27		def write
 28			@reply.note_type = :error
 29			@reply.note_text = <<~NOTE
 30				You are already registered with JMP number #{@tel}
 31			NOTE
 32			BLATHER << @reply
 33			nil
 34		end
 35	end
 36
 37	class Activation
 38		def self.for(iq, customer, tel)
 39			return EMPromise.resolve(new(iq, customer, tel)) if customer
 40
 41			# Create customer_id
 42			raise "TODO"
 43		end
 44
 45		def initialize(iq, customer, tel)
 46			@reply = iq.reply
 47			reply.allowed_actions = [:next]
 48
 49			@customer = customer
 50			@tel = tel
 51		end
 52
 53		attr_reader :reply, :customer, :tel
 54
 55		FORM_FIELDS = [
 56			{
 57				var: "activation_method",
 58				type: "list-single",
 59				label: "Activate using",
 60				required: true,
 61				options: [
 62					{
 63						value: "bitcoin",
 64						label: "Bitcoin"
 65					},
 66					{
 67						value: "credit_card",
 68						label: "Credit Card"
 69					},
 70					{
 71						value: "code",
 72						label: "Referral or Activation Code"
 73					}
 74				]
 75			},
 76			{
 77				var: "plan_name",
 78				type: "list-single",
 79				label: "What currency should your account balance be in?",
 80				required: true,
 81				options: [
 82					{
 83						value: "cad_beta_unlimited-v20210223",
 84						label: "Canadian Dollars"
 85					},
 86					{
 87						value: "usd_beta_unlimited-v20210223",
 88						label: "United States Dollars"
 89					}
 90				]
 91			}
 92		].freeze
 93
 94		def write
 95			form = reply.form
 96			form.type = :form
 97			form.title = "Activate JMP"
 98			form.instructions = "Going to activate #{tel} (TODO RATE CTR)"
 99			form.fields = FORM_FIELDS
100
101			COMMAND_MANAGER.write(reply).then { |iq|
102				Payment.for(iq, customer, tel)
103			}.then(&:write)
104		end
105	end
106
107	module Payment
108		def self.kinds
109			@kinds ||= {}
110		end
111
112		def self.for(iq, customer, tel)
113			kinds.fetch(iq.form.field("activation_method")&.value&.to_s&.to_sym) {
114				raise "Invalid activation method"
115			}.call(iq, customer, tel)
116		end
117
118		class Bitcoin
119			Payment.kinds[:bitcoin] = method(:new)
120
121			def initialize(iq, customer, tel)
122				@reply = iq.reply
123				reply.note_type = :info
124				reply.status = :completed
125
126				plan_name = iq.form.field("plan_name").value.to_s
127				@customer = customer.with_plan(plan_name)
128				@customer_id = customer.customer_id
129				@tel = tel
130				@addr = ELECTRUM.createnewaddress
131			end
132
133			attr_reader :reply, :customer_id, :tel
134
135			def save
136				EMPromise.all([
137					REDIS.mset(
138						"pending_tel_for-#{customer_id}", tel,
139						"pending_plan_for-#{customer_id}", @customer.plan_name
140					),
141					@addr.then do |addr|
142						REDIS.sadd("jmp_customer_btc_addresses-#{customer_id}", addr)
143					end
144				])
145			end
146
147			def note_text(amount, addr)
148				<<~NOTE
149					Activate your account by sending at least #{'%.6f' % amount} BTC to
150					#{addr}
151
152					You will receive a notification when your payment is complete.
153				NOTE
154			end
155
156			def write
157				EMPromise.all([
158					@addr,
159					save,
160					BTC_SELL_PRICES.public_send(@customer.currency.to_s.downcase)
161				]).then do |(addr, _, rate)|
162					min = CONFIG[:activation_amount] / rate
163					reply.note_text = note_text(min, addr)
164					BLATHER << reply
165					nil
166				end
167			end
168		end
169
170		class CreditCard
171			Payment.kinds[:credit_card] = ->(*args) { self.for(*args) }
172
173			def self.for(iq, customer, tel)
174				customer.payment_methods.then do |payment_methods|
175					if payment_methods.default_payment_method
176						Activate.new(iq, customer, tel)
177					else
178						new(iq, customer, tel)
179					end
180				end
181			end
182
183			def initialize(iq, customer, tel)
184				@customer = customer
185				@tel = tel
186
187				@reply = iq.reply
188				@reply.allowed_actions = [:next]
189				@reply.note_type = :info
190				@reply.note_text = "#{oob.desc}: #{oob.url}"
191			end
192
193			attr_reader :reply
194
195			def oob
196				oob = OOB.find_or_create(@reply.command)
197				oob.url = CONFIG[:credit_card_url].call(
198					@reply.to.stripped.to_s,
199					@customer.customer_id
200				)
201				oob.desc = "Add credit card, then return here and choose next"
202				oob
203			end
204
205			def write
206				COMMAND_MANAGER.write(@reply).then do |riq|
207					CreditCard.for(riq, @customer, @tel)
208				end
209			end
210
211			class Activate
212				def initialize(_iq, _customer, _tel)
213					raise "TODO"
214				end
215			end
216		end
217	end
218end