Merge branch 'prev'

Stephen Paul Weber created

* prev:
  Allow prev from mail-in registration
  Allow prev from invite code
  Allow prev from credit card form
  Make sure OOB comes first in payload
  Allow prev from Bitcoin registration
  Allow prev action on TelSelections search results

Change summary

lib/registration.rb       | 63 +++++++++++++++++++++++++++-------------
lib/tel_selections.rb     | 18 ++++++-----
test/test_registration.rb |  8 ++--
3 files changed, 56 insertions(+), 33 deletions(-)

Detailed changes

lib/registration.rb 🔗

@@ -185,7 +185,8 @@ class Registration
 				REDIS.setex("pending_tel_for-#{@customer.jid}", THIRTY_DAYS, tel)
 			end
 
-			def note_text(amount, addr)
+			def note_text(rate, addr)
+				amount = CONFIG[:activation_amount] / rate
 				<<~NOTE
 					Activate your account by sending at least #{'%.6f' % amount} BTC to
 					#{addr}
@@ -195,24 +196,31 @@ class Registration
 			end
 
 			def write
-				EMPromise.all([
-					addr,
-					save,
-					BTC_SELL_PRICES.public_send(@customer.currency.to_s.downcase)
-				]).then do |(addr, _, rate)|
-					min = CONFIG[:activation_amount] / rate
-					Command.finish(
-						note_text(min, addr) + @final_message.to_s, status: :canceled
-					)
+				EMPromise.all([addr_and_rate, save]).then do |((addr, rate), _)|
+					Command.reply { |reply|
+						reply.allowed_actions = [:prev]
+						reply.status = :canceled
+						reply.note_type = :info
+						reply.note_text = note_text(rate, addr) + @final_message.to_s
+					}.then(&method(:handle_possible_prev))
 				end
 			end
 
 		protected
 
-			def addr
-				@addr ||= @customer.btc_addresses.then { |addrs|
-					addrs.first || @customer.add_btc_address
-				}
+			def handle_possible_prev(iq)
+				raise "Action not allowed" unless iq.prev?
+
+				Activation.for(@customer, @tel).then(&:write)
+			end
+
+			def addr_and_rate
+				EMPromise.all([
+					@customer.btc_addresses.then { |addrs|
+						addrs.first || @customer.add_btc_address
+					},
+					BTC_SELL_PRICES.public_send(@customer.currency.to_s.downcase)
+				])
 			end
 		end
 
@@ -247,10 +255,13 @@ class Registration
 
 			def write
 				Command.reply { |reply|
-					reply.allowed_actions = [:next]
+					reply.allowed_actions = [:next, :prev]
+					toob = oob(reply)
 					reply.note_type = :info
-					reply.note_text = "#{oob(reply).desc}: #{oob(reply).url}"
-				}.then do
+					reply.note_text = "#{toob.desc}: #{toob.url}"
+				}.then do |iq|
+					next Activation.for(@customer, @tel).then(&:write) if iq.prev?
+
 					CreditCard.for(@customer, @tel, finish: @finish).then(&:write)
 				end
 			end
@@ -342,12 +353,14 @@ class Registration
 
 			def write
 				Command.reply { |reply|
-					reply.allowed_actions = [:next]
+					reply.allowed_actions = [:next, :prev]
 					add_form(reply)
 				}.then(&method(:parse))
 			end
 
 			def parse(iq)
+				return Activation.for(@customer, @tel).then(&:write) if iq.prev?
+
 				guard_too_many_tries.then {
 					verify(iq.form.field("code")&.value&.to_s)
 				}.then {
@@ -386,7 +399,9 @@ class Registration
 		class Mail
 			Payment.kinds[:mail] = method(:new)
 
-			def initialize(_customer, _tel, final_message: nil, **)
+			def initialize(customer, tel, final_message: nil, **)
+				@customer = customer
+				@tel = tel
 				@final_message = final_message
 			end
 
@@ -412,9 +427,15 @@ class Registration
 			end
 
 			def write
-				Command.finish(status: :canceled) do |reply|
+				Command.reply { |reply|
+					reply.allowed_actions = [:prev]
+					reply.status = :canceled
 					reply.command << form
-				end
+				}.then { |iq|
+					raise "Action not allowed" unless iq.prev?
+
+					Activation.for(@customer, @tel).then(&:write)
+				}
 			end
 		end
 	end

lib/tel_selections.rb 🔗

@@ -49,14 +49,16 @@ class TelSelections
 		end
 
 		def choose_from_list(tns)
-			if tns.empty?
-				choose_tel(error: "No numbers found, try another search.")
-			else
-				Command.reply { |reply|
-					reply.allowed_actions = [:next]
-					reply.command << FormTemplate.render("tn_list", tns: tns)
-				}.then { |iq| iq.form.field("tel").value.to_s.strip }
-			end
+			raise "No numbers found, try another search." if tns.empty?
+
+			Command.reply { |reply|
+				reply.allowed_actions = [:next, :prev]
+				reply.command << FormTemplate.render("tn_list", tns: tns)
+			}.then { |iq|
+				next choose_tel if iq.prev?
+
+				iq.form.field("tel").value.to_s.strip
+			}
 		end
 
 		class AvailableNumber

test/test_registration.rb 🔗

@@ -337,9 +337,9 @@ class RegistrationTest < Minitest::Test
 					You will receive a notification when your payment is complete.
 				NOTE
 				blather = Minitest::Mock.new
-				blather.expect(
-					:<<,
-					nil,
+				Command::COMMAND_MANAGER.expect(
+					:write,
+					EMPromise.reject(SessionManager::Timeout.new),
 					[Matching.new do |reply|
 						assert_equal :canceled, reply.status
 						assert_equal :info, reply.note_type
@@ -391,7 +391,7 @@ class RegistrationTest < Minitest::Test
 						:write,
 						EMPromise.reject(:test_result),
 						[Matching.new do |reply|
-							assert_equal [:execute, :next], reply.allowed_actions
+							assert_equal [:execute, :next, :prev], reply.allowed_actions
 							assert_equal(
 								"Add credit card, then return here to continue: " \
 								"http://creditcard.example.com",