@@ -16,6 +16,12 @@ require_relative "./proxied_jid"
require_relative "./tel_selections"
require_relative "./welcome_message"
+def reload_customer(customer)
+ EMPromise.resolve(nil).then do
+ Command.execution.customer_repo.find(customer.customer_id)
+ end
+end
+
class Registration
def self.for(customer, google_play_userid, tel_selections)
if (reg = customer.registered?)
@@ -41,13 +47,6 @@ class Registration
end
end
- def self.guard_onboarding_subaccounts(customer)
- customer_domain = ProxiedJID.new(customer.jid).domain
- return unless customer_domain == CONFIG[:onboarding_domain]
-
- raise "Please create a new Jabber ID before creating a subaccount."
- end
-
class Registered
def self.for(customer, tel)
jid = ProxiedJID.new(customer.jid).unproxied
@@ -108,7 +107,6 @@ class Registration
def initialize(customer, tel)
@customer = customer
@tel = tel
- @invites = InvitesRepo.new(DB, REDIS)
end
attr_reader :customer, :tel
@@ -125,33 +123,15 @@ class Registration
end
def next_step(iq)
- code = iq.form.field("code")&.value&.to_s
- save_customer_plan(iq, code).then {
- finish_if_valid_invite(code)
- }.catch_only(InvitesRepo::Invalid) do
- @invites.stash_code(customer.customer_id, code).then do
- Payment.for(iq, @customer, @tel).then(&:write)
- end
- end
- end
-
- protected
-
- def finish_if_valid_invite(code)
- @invites.claim_code(@customer.customer_id, code) {
- @customer.activate_plan_starting_now
- }.then do
- Finish.new(@customer, @tel).write
- end
- end
-
- def save_customer_plan(iq, code)
- Registration.guard_onboarding_subaccounts(@customer)
-
- ParentCodeRepo.new(redis: REDIS, db: DB).find(code).then do |parent|
+ EMPromise.resolve(nil).then do
plan = Plan.for_registration(iq.form.field("plan_name").value.to_s)
- @customer = @customer.with_plan(plan.name, parent_customer_id: parent)
- @customer.save_plan!
+ @customer = @customer.with_plan(plan.name)
+ Registration::Payment::InviteCode.new(
+ @customer, @tel, finish: Finish, db: DB, redis: REDIS
+ ).parse(iq, force_save_plan: true)
+ .catch_only(InvitesRepo::Invalid) do
+ Payment.for(iq, @customer, @tel).then(&:write)
+ end
end
end
@@ -279,10 +259,16 @@ class Registration
@kinds ||= {}
end
- def self.for(iq, customer, tel, final_message: nil, finish: Finish)
+ def self.for(
+ iq, customer, tel,
+ finish: Finish, maybe_bill: MaybeBill,
+ price: CONFIG[:activation_amount] + tel.price
+ )
kinds.fetch(iq.form.field("activation_method")&.value&.to_s&.to_sym) {
raise "Invalid activation method"
- }.call(customer, tel, final_message: final_message, finish: finish)
+ }.call(
+ customer, tel, finish: finish, maybe_bill: maybe_bill, price: price
+ )
end
class CryptoPaymentMethod
@@ -298,11 +284,14 @@ class Registration
raise NotImplementedError, "Subclass must implement"
end
- def initialize(customer, tel, final_message: nil, **)
+ def initialize(
+ customer, tel,
+ price: CONFIG[:activation_amount] + tel.price, **
+ )
@customer = customer
@customer_id = customer.customer_id
@tel = tel
- @final_message = final_message
+ @price = price
end
def save
@@ -312,13 +301,10 @@ class Registration
attr_reader :customer_id, :tel
def form(rate, addr)
- amount = CONFIG[:activation_amount] / rate
-
FormTemplate.render(
reg_form_name,
- amount: amount,
- addr: addr,
- final_message: @final_message
+ amount: @price / rate,
+ addr: addr
)
end
@@ -392,34 +378,45 @@ class Registration
end
end
- class CreditCard
- Payment.kinds[:credit_card] = ->(*args, **kw) { self.for(*args, **kw) }
+ class MaybeBill
+ def initialize(customer, tel, finish: Finish)
+ @customer = customer
+ @tel = tel
+ @finish = finish
+ end
- def self.for(in_customer, tel, finish: Finish, **)
- reload_customer(in_customer).then do |(customer, payment_methods)|
+ def call
+ reload_customer(@customer).then do |customer|
if customer.balance >= CONFIG[:activation_amount_accept]
- next BillPlan.new(customer, tel, finish: finish)
+ next BillPlan.new(customer, @tel, finish: @finish)
end
- if (method = payment_methods.default_payment_method)
- next Activate.new(customer, method, tel, finish: finish)
- end
-
- new(customer, tel, finish: finish)
+ yield customer
end
end
+ end
- def self.reload_customer(customer)
- EMPromise.all([
- Command.execution.customer_repo.find(customer.customer_id),
- customer.payment_methods
- ])
+ class JustCharge
+ def initialize(customer, *, **)
+ @customer = customer
end
- def initialize(customer, tel, finish: Finish)
+ def call; end
+ end
+
+ class CreditCard
+ Payment.kinds[:credit_card] = method(:new)
+
+ def initialize(
+ customer, tel,
+ finish: Finish, maybe_bill: MaybeBill,
+ price: CONFIG[:activation_amount] + tel.price
+ )
@customer = customer
@tel = tel
@finish = finish
+ @maybe_bill = maybe_bill.new(customer, tel, finish: finish)
+ @price = price
end
def oob(reply)
@@ -427,8 +424,8 @@ class Registration
oob.url = CONFIG[:credit_card_url].call(
reply.to.stripped.to_s.gsub("\\", "%5C"),
@customer.customer_id
- ) + "&amount=#{CONFIG[:activation_amount]}"
- oob.desc = "Add credit card, save, then next here to continue"
+ ) + "&amount=#{@price.ceil}"
+ oob.desc = "Pay by credit card, save, then next here to continue"
oob
end
@@ -441,85 +438,13 @@ class Registration
}.then do |iq|
next Activation.for(@customer, nil, @tel).then(&:write) if iq.prev?
- CreditCard.for(@customer, @tel, finish: @finish).then(&:write)
- end
- end
-
- class Activate
- def initialize(customer, payment_method, tel, finish: Finish)
- @customer = customer
- @payment_method = payment_method
- @tel = tel
- @finish = finish
- end
-
- def write
- CreditCardSale.create(
- @customer,
- amount: CONFIG[:activation_amount],
- payment_method: @payment_method
- ).then(
- ->(_) { sold },
- ->(_) { declined }
- )
- end
-
- protected
-
- def sold
- BillPlan.new(@customer, @tel, finish: @finish).write
- end
-
- DECLINE_MESSAGE =
- "Your bank declined the transaction. " \
- "Often this happens when a person's credit card " \
- "is a US card that does not support international " \
- "transactions, as JMP is not based in the USA, though " \
- "we do support transactions in USD.\n\n" \
- "You may add another card"
-
- def decline_oob(reply)
- oob = OOB.find_or_create(reply.command)
- oob.url = CONFIG[:credit_card_url].call(
- reply.to.stripped.to_s.gsub("\\", "%5C"),
- @customer.customer_id
- ) + "&amount=#{CONFIG[:activation_amount]}"
- oob.desc = DECLINE_MESSAGE
- oob
- end
-
- def declined
- Command.reply { |reply|
- reply_oob = decline_oob(reply)
- reply.allowed_actions = [:next]
- reply.note_type = :error
- reply.note_text = "#{reply_oob.desc}: #{reply_oob.url}"
- }.then do
- CreditCard.for(@customer, @tel, finish: @finish).then(&:write)
- end
+ @maybe_bill.call { self }&.then(&:write)
end
end
end
class InviteCode
- Payment.kinds[:code] = ->(*args, **kw) { self.for(*args, **kw) }
-
- def self.for(in_customer, tel, finish: Finish, **)
- reload_customer(in_customer).then do |customer|
- if customer.balance >= CONFIG[:activation_amount_accept]
- next BillPlan.new(customer, tel, finish: finish)
- end
-
- msg = if customer.balance.positive?
- "Account balance not enough to cover the activation"
- end
- new(customer, tel, error: msg, finish: Finish)
- end
- end
-
- def self.reload_customer(customer)
- Command.execution.customer_repo.find(customer.customer_id)
- end
+ Payment.kinds[:code] = method(:new)
FIELDS = [{
var: "code",
@@ -528,12 +453,16 @@ class Registration
required: true
}].freeze
- def initialize(customer, tel, error: nil, finish: Finish, **)
+ def initialize(
+ customer, tel,
+ error: nil, finish: Finish, db: DB, redis: REDIS, **
+ )
@customer = customer
@tel = tel
@error = error
@finish = finish
- @parent_code_repo = ParentCodeRepo.new(redis: REDIS, db: DB)
+ @invites_repo = InvitesRepo.new(db, redis)
+ @parent_code_repo = ParentCodeRepo.new(db: db, redis: redis)
end
def add_form(reply)
@@ -548,48 +477,44 @@ class Registration
Command.reply { |reply|
reply.allowed_actions = [:next, :prev]
add_form(reply)
- }.then(&method(:parse))
+ }.then(&method(:parse)).catch_only(InvitesRepo::Invalid) { |e|
+ invalid_code(e).write
+ }
end
- def parse(iq)
+ def parse(iq, force_save_plan: false)
return Activation.for(@customer, nil, @tel).then(&:write) if iq.prev?
- verify(iq.form.field("code")&.value&.to_s)
- .catch_only(InvitesRepo::Invalid, &method(:invalid_code))
+ verify(iq.form.field("code")&.value&.to_s, force_save_plan)
.then(&:write)
end
protected
def invalid_code(e)
- InviteCode.new(@customer, @tel, error: e.message)
+ self.class.new(@customer, @tel, error: e.message, finish: @finish)
end
def customer_id
@customer.customer_id
end
- def verify(code)
- @parent_code_repo.find(code).then do |parent_customer_id|
- if parent_customer_id
- set_parent(parent_customer_id)
- else
- InvitesRepo.new(DB, REDIS).claim_code(customer_id, code) {
+ def verify(code, force_save_plan)
+ @parent_code_repo.claim_code(@customer, code) {
+ check_parent_balance
+ }.catch_only(ParentCodeRepo::Invalid) {
+ (@customer.save_plan! if force_save_plan).then do
+ @invites_repo.claim_code(customer_id, code) {
@customer.activate_plan_starting_now
- }.then { Finish.new(@customer, @tel) }
+ }.then { @finish.new(@customer, @tel) }
end
- end
+ }
end
- def set_parent(parent_customer_id)
- Registration.guard_onboarding_subaccounts(@customer)
-
- @customer = @customer.with_plan(
- @customer.plan_name,
- parent_customer_id: parent_customer_id
- )
- @customer.save_plan!.then do
- self.class.for(@customer, @tel, finish: @finish)
+ def check_parent_balance
+ MaybeBill.new(@customer, @tel, finish: @finish).call do
+ msg = "Account balance not enough to cover the activation"
+ invalid_code(RuntimeError.new(msg))
end
end
end
@@ -597,17 +522,20 @@ class Registration
class Mail
Payment.kinds[:mail] = method(:new)
- def initialize(customer, tel, final_message: nil, **)
+ def initialize(
+ customer, tel,
+ price: CONFIG[:activation_amount] + tel.price, **
+ )
@customer = customer
@tel = tel
- @final_message = final_message
+ @price = price
end
def form
FormTemplate.render(
"registration/mail",
currency: @customer.currency,
- final_message: @final_message,
+ price: @price,
**onboarding_extras
)
end
@@ -645,11 +573,39 @@ class Registration
def write
@customer.bill_plan(note: "Bill #{@tel} for first month").then do
- @finish.new(@customer, @tel).write
+ updated_customer =
+ @customer.with_balance(@customer.balance - @customer.monthly_price)
+ @finish.new(updated_customer, @tel).write
end
end
end
+ class BuyNumber
+ def initialize(customer, tel)
+ @customer = customer
+ @tel = tel
+ end
+
+ def write
+ Command.reply { |reply|
+ reply.command << FormTemplate.render(
+ "registration/buy_number",
+ tel: @tel
+ )
+ }.then(&method(:parse)).then(&:write)
+ end
+
+ protected
+
+ def parse(iq)
+ Payment.for(
+ iq, @customer, @tel,
+ maybe_bill: ::Registration::Payment::JustCharge,
+ price: @tel.price
+ )
+ end
+ end
+
class Finish
def initialize(customer, tel)
@customer = customer
@@ -658,6 +614,8 @@ class Registration
end
def write
+ return buy_number if @customer.balance < @tel.price
+
@tel.order(DB, @customer).then(
->(_) { customer_active_tel_purchased },
method(:number_purchase_error)
@@ -666,6 +624,14 @@ class Registration
protected
+ def buy_number
+ BuyNumber.new(@customer, @tel).write.then do
+ reload_customer(@customer).then { |customer|
+ Finish.new(customer, @tel)
+ }.then(&:write)
+ end
+ end
+
def number_purchase_error(e)
Command.log.error "number_purchase_error", e
TEL_SELECTIONS.delete(@customer.jid).then {
@@ -712,7 +678,8 @@ class Registration
EMPromise.all([
TEL_SELECTIONS.delete(@customer.jid),
put_default_fwd,
- use_referral_code
+ use_referral_code,
+ @tel.charge(@customer)
])
}.then do
FinishOnboarding.for(@customer, @tel).then(&:write)
@@ -155,7 +155,8 @@ class RegistrationTest < Minitest::Test
def setup
@customer = Minitest::Mock.new(customer)
- @activation = Registration::Activation.new(@customer, "+15555550000")
+ @tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
+ @activation = Registration::Activation.new(@customer, @tel)
end
def test_write
@@ -167,7 +168,7 @@ class RegistrationTest < Minitest::Test
[Matching.new do |iq|
assert_equal :form, iq.form.type
assert_equal(
- "You've selected +15555550000 as your JMP number.",
+ "You've selected (555) 555-0000 as your JMP number.",
iq.form.instructions.lines.first.chomp
)
end]
@@ -179,7 +180,7 @@ class RegistrationTest < Minitest::Test
Registration::Activation::Payment.expect(
:for,
EMPromise.reject(:test_result),
- [Blather::Stanza::Iq, @customer, "+15555550000"]
+ [Blather::Stanza::Iq, @customer, @tel]
)
assert_equal(
:test_result,
@@ -191,6 +192,43 @@ class RegistrationTest < Minitest::Test
end
em :test_write
+ def test_write_with_onboarding_jid
+ Command::COMMAND_MANAGER.expect(
+ :write,
+ EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
+ iq.form.fields = [{ var: "plan_name", value: "test_usd" }]
+ }),
+ [Matching.new do |iq|
+ assert_equal :form, iq.form.type
+ assert_equal(
+ "You've selected (555) 555-0000 as your JMP number.",
+ iq.form.instructions.lines.first.chomp
+ )
+ end]
+ )
+ @customer.expect(
+ :jid,
+ Blather::JID.new("test\\40onboarding.example.com@proxy")
+ )
+ @customer.expect(:with_plan, @customer) do |*args, **|
+ assert_equal ["test_usd"], args
+ end
+ @customer.expect(:save_plan!, EMPromise.resolve(nil), [])
+ Registration::Activation::Payment.expect(
+ :for,
+ EMPromise.reject(:test_result),
+ [Blather::Stanza::Iq, @customer, @tel]
+ )
+ assert_equal(
+ :test_result,
+ execute_command { @activation.write.catch { |e| e } }
+ )
+ assert_mock Command::COMMAND_MANAGER
+ assert_mock @customer
+ assert_mock Registration::Activation::Payment
+ end
+ em :test_write_with_onboarding_jid
+
def test_write_bad_plan
Command::COMMAND_MANAGER.expect(
:write,
@@ -200,7 +238,7 @@ class RegistrationTest < Minitest::Test
[Matching.new do |iq|
assert_equal :form, iq.form.type
assert_equal(
- "You've selected +15555550000 as your JMP number.",
+ "You've selected (555) 555-0000 as your JMP number.",
iq.form.instructions.lines.first.chomp
)
end]
@@ -226,7 +264,7 @@ class RegistrationTest < Minitest::Test
[Matching.new do |iq|
assert_equal :form, iq.form.type
assert_equal(
- "You've selected +15555550000 as your JMP number.",
+ "You've selected (555) 555-0000 as your JMP number.",
iq.form.instructions.lines.first.chomp
)
end]
@@ -245,7 +283,7 @@ class RegistrationTest < Minitest::Test
Registration::Activation::Finish.expect(
:new,
OpenStruct.new(write: EMPromise.reject(:test_result)),
- [@customer, "+15555550000"]
+ [@customer, @tel]
)
assert_equal(
:test_result,
@@ -270,7 +308,7 @@ class RegistrationTest < Minitest::Test
[Matching.new do |iq|
assert_equal :form, iq.form.type
assert_equal(
- "You've selected +15555550000 as your JMP number.",
+ "You've selected (555) 555-0000 as your JMP number.",
iq.form.instructions.lines.first.chomp
)
end]
@@ -288,7 +326,7 @@ class RegistrationTest < Minitest::Test
Registration::Activation::Payment.expect(
:for,
EMPromise.reject(:test_result),
- [Blather::Stanza::Iq, @customer, "+15555550000"]
+ [Blather::Stanza::Iq, @customer, @tel]
)
assert_equal(
:test_result,
@@ -308,52 +346,57 @@ class RegistrationTest < Minitest::Test
em :test_write_with_group_code
def test_write_with_parent_code
- Command::COMMAND_MANAGER.expect(
- :write,
- EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
- iq.form.fields = [
- { var: "plan_name", value: "test_usd" },
- { var: "code", value: "PARENT_CODE" }
- ]
- }),
- [Matching.new do |iq|
- assert_equal :form, iq.form.type
- assert_equal(
- "You've selected +15555550000 as your JMP number.",
- iq.form.instructions.lines.first.chomp
- )
- end]
- )
- Registration::Activation::DB.expect(
- :query_one, {}, [String, "1"], default: {}
- )
- Registration::Activation::DB.expect(
- :query_one, { c: 0 }, [String, "1"], default: { c: 0 }
- )
- @customer.expect(:with_plan, @customer) do |*args, **kwargs|
- assert_equal ["test_usd"], args
- assert_equal({ parent_customer_id: "1" }, kwargs)
+ execute_command do
+ Command::COMMAND_MANAGER.expect(
+ :write,
+ EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
+ iq.form.fields = [
+ { var: "plan_name", value: "test_usd" },
+ { var: "code", value: "PARENT_CODE" }
+ ]
+ }),
+ [Matching.new do |iq|
+ assert_equal :form, iq.form.type
+ assert_equal(
+ "You've selected (555) 555-0000 as your JMP number.",
+ iq.form.instructions.lines.first.chomp
+ )
+ end]
+ )
+ Registration::Activation::DB.expect(
+ :query_one, {}, [String, "1"], default: {}
+ )
+ Registration::Activation::DB.expect(
+ :query_one, { c: 0 }, [String, "1"], default: { c: 0 }
+ )
+ @customer.expect(:with_plan, @customer) do |*args, **|
+ assert_equal ["test_usd"], args
+ end
+ @customer.expect(:with_plan, @customer) do |*, **kwargs|
+ assert_equal({ parent_customer_id: "1" }, kwargs)
+ end
+ @customer.expect(:save_plan!, EMPromise.resolve(nil), [])
+ @customer.expect(:balance, 100, [])
+ Command.execution.customer_repo.expect(
+ :find,
+ EMPromise.resolve(@customer), ["test"]
+ )
+ Registration::Payment::MaybeBill::BillPlan.expect(
+ :new,
+ EMPromise.reject(:test_result)
+ ) do |*args, **|
+ assert_equal @tel, args[1]
+ end
+ assert_equal(
+ :test_result,
+ @activation.write.catch { |e| e }.sync
+ )
end
- @customer.expect(:save_plan!, EMPromise.resolve(nil), [])
- Registration::Activation::DB.expect(:transaction, []) { |&blk| blk.call }
- Registration::Activation::DB.expect(
- :exec,
- OpenStruct.new(cmd_tuples: 0),
- [String, ["test", "PARENT_CODE"]]
- )
- Registration::Activation::Payment.expect(
- :for,
- EMPromise.reject(:test_result),
- [Blather::Stanza::Iq, @customer, "+15555550000"]
- )
- assert_equal(
- :test_result,
- execute_command { @activation.write.catch { |e| e } }
- )
assert_mock Command::COMMAND_MANAGER
assert_mock @customer
assert_mock Registration::Activation::Payment
assert_mock Registration::Activation::DB
+ assert_mock Registration::Payment::MaybeBill::BillPlan
end
em :test_write_with_parent_code
@@ -369,14 +412,24 @@ class RegistrationTest < Minitest::Test
[Matching.new do |iq|
assert_equal :form, iq.form.type
assert_equal(
- "You've selected +15555550000 as your JMP number.",
+ "You've selected (555) 555-0000 as your JMP number.",
iq.form.instructions.lines.first.chomp
)
end]
)
- @customer.expect(:jid, Blather::JID.new("test@onboarding.example.com"))
+ Registration::Activation::DB.expect(
+ :query_one, {}, [String, "1"], default: {}
+ )
+ Registration::Activation::DB.expect(
+ :query_one, { c: 0 }, [String, "1"], default: { c: 0 }
+ )
+ @customer.expect(:with_plan, @customer, ["test_usd"])
+ @customer.expect(
+ :jid,
+ Blather::JID.new("test\\40onboarding.example.com@proxy")
+ )
iq = Blather::Stanza::Iq::Command.new
- iq.from = "test@onboarding.example.com"
+ iq.from = "test\\40onboarding.example.com@proxied"
assert_equal(
"Please create a new Jabber ID before creating a subaccount.",
execute_command(iq) { @activation.write.catch(&:to_s) }
@@ -400,7 +453,7 @@ class RegistrationTest < Minitest::Test
[Matching.new do |iq|
assert_equal :form, iq.form.type
assert_equal(
- "You've selected +15555550000 as your JMP number.",
+ "You've selected (555) 555-0000 as your JMP number.",
iq.form.instructions.lines.first.chomp
)
end]
@@ -434,7 +487,7 @@ class RegistrationTest < Minitest::Test
[Matching.new do |iq|
assert_equal :form, iq.form.type
assert_equal(
- "You've selected +15555550000 as your JMP number.",
+ "You've selected (555) 555-0000 as your JMP number.",
iq.form.instructions.lines.first.chomp
)
end]
@@ -462,8 +515,9 @@ class RegistrationTest < Minitest::Test
Registration::Activation::Allow::DB = Minitest::Mock.new
def test_write_credit_to_nil
+ tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
cust = Minitest::Mock.new(customer("test"))
- allow = Registration::Activation::Allow.new(cust, "+15555550000", nil)
+ allow = Registration::Activation::Allow.new(cust, tel, nil)
Command::COMMAND_MANAGER.expect(
:write,
@@ -473,7 +527,7 @@ class RegistrationTest < Minitest::Test
[Matching.new do |iq|
assert_equal :form, iq.form.type
assert_equal(
- "You've selected +15555550000 as your JMP number.",
+ "You've selected (555) 555-0000 as your JMP number.",
iq.form.instructions.lines.first.chomp
)
assert_equal 1, iq.form.fields.length
@@ -498,8 +552,9 @@ class RegistrationTest < Minitest::Test
def test_write_credit_to_refercust
cust = Minitest::Mock.new(customer("test"))
+ tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
allow = Registration::Activation::Allow.new(
- cust, "+15555550000", "refercust"
+ cust, tel, "refercust"
)
Command::COMMAND_MANAGER.expect(
@@ -510,7 +565,7 @@ class RegistrationTest < Minitest::Test
[Matching.new do |iq|
assert_equal :form, iq.form.type
assert_equal(
- "You've selected +15555550000 as your JMP number.",
+ "You've selected (555) 555-0000 as your JMP number.",
iq.form.instructions.lines.first.chomp
)
assert_equal 1, iq.form.fields.length
@@ -545,10 +600,11 @@ class RegistrationTest < Minitest::Test
def setup
@customer = customer
+ @tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
@google_play = Registration::Activation::GooglePlay.new(
@customer,
"abcd",
- "+15555550000"
+ @tel
)
end
@@ -561,7 +617,7 @@ class RegistrationTest < Minitest::Test
[Matching.new do |iq|
assert_equal :form, iq.form.type
assert_equal(
- "You've selected +15555550000 as your JMP number.",
+ "You've selected (555) 555-0000 as your JMP number.",
iq.form.instructions.lines.first.chomp
)
end]
@@ -580,7 +636,7 @@ class RegistrationTest < Minitest::Test
Registration::Activation::GooglePlay::Finish.expect(
:new,
OpenStruct.new(write: EMPromise.reject(:test_result)),
- [Customer, "+15555550000"]
+ [Customer, @tel]
)
result = execute_command { @google_play.write.catch { |e| e } }
assert_equal :test_result, result
@@ -596,37 +652,29 @@ class RegistrationTest < Minitest::Test
CustomerFinancials::BRAINTREE = Minitest::Mock.new
def test_for_bitcoin
+ tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
iq = Blather::Stanza::Iq::Command.new
iq.form.fields = [
{ var: "activation_method", value: "bitcoin" },
{ var: "plan_name", value: "test_usd" }
]
- result = Registration::Payment.for(iq, customer, "+15555550000")
+ result = Registration::Payment.for(iq, customer, tel)
assert_kind_of Registration::Payment::Bitcoin, result
end
def test_for_bch
+ tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
iq = Blather::Stanza::Iq::Command.new
iq.form.fields = [
{ var: "activation_method", value: "bch" },
{ var: "plan_name", value: "test_usd" }
]
- result = Registration::Payment.for(iq, customer, "+15555550000")
+ result = Registration::Payment.for(iq, customer, tel)
assert_kind_of Registration::Payment::BCH, result
end
def test_for_credit_card
- braintree_customer = Minitest::Mock.new
- CustomerFinancials::BRAINTREE.expect(
- :customer,
- braintree_customer
- )
- CustomerFinancials::REDIS.expect(:smembers, [], ["block_credit_cards"])
- braintree_customer.expect(
- :find,
- EMPromise.resolve(OpenStruct.new(payment_methods: [])),
- ["test"]
- )
+ tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
iq = Blather::Stanza::Iq::Command.new
iq.from = "test@example.com"
iq.form.fields = [
@@ -639,8 +687,8 @@ class RegistrationTest < Minitest::Test
Registration::Payment.for(
iq,
cust,
- ""
- ).sync
+ tel
+ )
end
assert_kind_of Registration::Payment::CreditCard, result
end
@@ -658,7 +706,7 @@ class RegistrationTest < Minitest::Test
Registration::Payment.for(
iq,
cust,
- "+15555550000"
+ TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
)
end
assert_kind_of Registration::Payment::InviteCode, result
@@ -677,9 +725,10 @@ class RegistrationTest < Minitest::Test
:add_btc_address,
EMPromise.resolve("testaddr")
)
+ @tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
@bitcoin = Registration::Payment::Bitcoin.new(
@customer,
- "+15555550000"
+ @tel
)
end
@@ -726,9 +775,10 @@ class RegistrationTest < Minitest::Test
:add_bch_address,
EMPromise.resolve("testaddr")
)
+ @tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
@bch = Registration::Payment::BCH.new(
@customer,
- "+15555550000"
+ @tel
)
end
@@ -765,13 +815,15 @@ class RegistrationTest < Minitest::Test
class CreditCardTest < Minitest::Test
def setup
+ @tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
@credit_card = Registration::Payment::CreditCard.new(
customer,
- "+15555550000"
+ @tel
)
end
- def test_for
+ def test_new
+ tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
cust = Minitest::Mock.new(customer)
cust.expect(
:payment_methods,
@@ -780,32 +832,12 @@ class RegistrationTest < Minitest::Test
execute_command do
Command.execution.customer_repo.expect(:find, cust, ["test"])
assert_kind_of(
- Registration::Payment::CreditCard::Activate,
- Registration::Payment::CreditCard.for(
- cust,
- "+15555550000"
- ).sync
+ Registration::Payment::CreditCard,
+ Registration::Payment::CreditCard.new(cust, tel)
)
end
end
- em :test_for
-
- def test_for_has_balance
- cust = Minitest::Mock.new(customer)
- cust.expect(:balance, 100)
- cust.expect(:payment_methods, EMPromise.resolve(nil))
- execute_command do
- Command.execution.customer_repo.expect(:find, cust, ["test"])
- assert_kind_of(
- Registration::BillPlan,
- Registration::Payment::CreditCard.for(
- cust,
- "+15555550000"
- ).sync
- )
- end
- end
- em :test_for_has_balance
+ em :test_new
def test_write
result = execute_command do
@@ -815,7 +847,7 @@ class RegistrationTest < Minitest::Test
[Matching.new do |reply|
assert_equal [:execute, :next, :prev], reply.allowed_actions
assert_equal(
- "Add credit card, save, then next here to continue: " \
+ "Pay by credit card, save, then next here to continue: " \
"http://creditcard.example.com?&amount=1",
reply.note.content
)
@@ -832,9 +864,10 @@ class RegistrationTest < Minitest::Test
class MailTest < Minitest::Test
def setup
+ @tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
@mail = Registration::Payment::Mail.new(
customer(plan_name: "test_cad"),
- "+15555550000"
+ @tel
)
end
@@ -865,88 +898,6 @@ class RegistrationTest < Minitest::Test
em :test_write
end
- class ActivateTest < Minitest::Test
- Registration::Payment::CreditCard::Activate::Finish =
- Minitest::Mock.new
- Registration::Payment::CreditCard::Activate::CreditCardSale =
- Minitest::Mock.new
- Command::COMMAND_MANAGER = Minitest::Mock.new
-
- def test_write
- customer = Minitest::Mock.new(
- customer(plan_name: "test_usd")
- )
- Registration::Payment::CreditCard::Activate::CreditCardSale.expect(
- :create,
- EMPromise.resolve(nil)
- ) do |acustomer, amount:, payment_method:|
- assert_operator customer, :===, acustomer
- assert_equal CONFIG[:activation_amount], amount
- assert_equal :test_default_method, payment_method
- end
- customer.expect(
- :bill_plan,
- nil,
- note: "Bill +15555550000 for first month"
- )
- Registration::Payment::CreditCard::Activate::Finish.expect(
- :new,
- OpenStruct.new(write: nil),
- [customer, "+15555550000"]
- )
- execute_command do
- Registration::Payment::CreditCard::Activate.new(
- customer,
- :test_default_method,
- "+15555550000"
- ).write
- end
- Registration::Payment::CreditCard::Activate::CreditCardSale.verify
- customer.verify
- Registration::Payment::CreditCard::Activate::Finish.verify
- end
- em :test_write
-
- def test_write_declines
- customer = Minitest::Mock.new(
- customer(plan_name: "test_usd")
- )
- iq = Blather::Stanza::Iq::Command.new
- iq.from = "test@example.com"
- msg = Registration::Payment::CreditCard::Activate::DECLINE_MESSAGE
- Command::COMMAND_MANAGER.expect(
- :write,
- EMPromise.reject(:test_result),
- [Matching.new do |reply|
- assert_equal :error, reply.note_type
- assert_equal(
- "#{msg}: http://creditcard.example.com?&amount=1",
- reply.note.content
- )
- end]
- )
- result = execute_command do
- Registration::Payment::CreditCard::Activate::CreditCardSale.expect(
- :create,
- EMPromise.reject("declined")
- ) do |acustomer, amount:, payment_method:|
- assert_operator customer, :===, acustomer
- assert_equal CONFIG[:activation_amount], amount
- assert_equal :test_default_method, payment_method
- end
-
- Registration::Payment::CreditCard::Activate.new(
- customer,
- :test_default_method,
- "+15555550000"
- ).write.catch { |e| e }
- end
- assert_equal :test_result, result
- Registration::Payment::CreditCard::Activate::CreditCardSale.verify
- end
- em :test_write_declines
- end
-
class InviteCodeTest < Minitest::Test
Registration::Payment::InviteCode::DB =
Minitest::Mock.new
@@ -955,9 +906,13 @@ class RegistrationTest < Minitest::Test
Command::COMMAND_MANAGER = Minitest::Mock.new
Registration::Payment::InviteCode::Finish =
Minitest::Mock.new
- Registration::Payment::InviteCode::BillPlan =
+ Registration::Payment::MaybeBill::BillPlan =
Minitest::Mock.new
+ def setup
+ @tel = TelSelections::ChooseTel::Tn.for_pending_value("+15555550000")
+ end
+
def test_write
customer = customer(plan_name: "test_usd")
Registration::Payment::InviteCode::DB.expect(:transaction, true, [])
@@ -966,7 +921,7 @@ class RegistrationTest < Minitest::Test
OpenStruct.new(write: nil),
[
customer,
- "+15555550000"
+ @tel
]
)
execute_command do
@@ -995,7 +950,7 @@ class RegistrationTest < Minitest::Test
Registration::Payment::InviteCode.new(
customer,
- "+15555550000"
+ @tel
).write
end
assert_mock Command::COMMAND_MANAGER
@@ -1007,7 +962,7 @@ class RegistrationTest < Minitest::Test
def test_write_parent_code
customer = customer(plan_name: "test_usd")
- Registration::Payment::InviteCode::BillPlan.expect(
+ Registration::Payment::MaybeBill::BillPlan.expect(
:new,
OpenStruct.new(write: nil)
) { |*| true }
@@ -1058,19 +1013,24 @@ class RegistrationTest < Minitest::Test
Registration::Payment::InviteCode.new(
customer,
- "+15555550000"
+ @tel
).write
end
assert_mock Command::COMMAND_MANAGER
assert_mock Registration::Payment::InviteCode::DB
assert_mock Registration::Payment::InviteCode::REDIS
- assert_mock Registration::Payment::InviteCode::BillPlan
+ assert_mock Registration::Payment::MaybeBill::BillPlan
end
em :test_write_parent_code
def test_write_bad_code
result = execute_command do
customer = customer(plan_name: "test_usd")
+ Registration::Payment::InviteCode::REDIS.expect(
+ :set,
+ EMPromise.resolve(nil),
+ ["jmp_customer_pending_invite-test", "abc"]
+ )
Registration::Payment::InviteCode::REDIS.expect(
:get,
EMPromise.resolve(0),
@@ -1131,7 +1091,7 @@ class RegistrationTest < Minitest::Test
Registration::Payment::InviteCode.new(
customer,
- "+15555550000"
+ @tel
).write.catch { |e| e }
end
assert_equal :test_result, result
@@ -1144,6 +1104,11 @@ class RegistrationTest < Minitest::Test
def test_write_group_code
result = execute_command do
customer = customer(plan_name: "test_usd")
+ Registration::Payment::InviteCode::REDIS.expect(
+ :set,
+ EMPromise.resolve(nil),
+ ["jmp_customer_pending_invite-test", "abc"]
+ )
Registration::Payment::InviteCode::REDIS.expect(
:get,
EMPromise.resolve(0),
@@ -1204,7 +1169,7 @@ class RegistrationTest < Minitest::Test
Registration::Payment::InviteCode.new(
customer,
- "+15555550000"
+ @tel
).write.catch { |e| e }
end
assert_equal :test_result, result
@@ -1249,7 +1214,7 @@ class RegistrationTest < Minitest::Test
)
Registration::Payment::InviteCode.new(
customer,
- "+15555550000"
+ @tel
).write.catch { |e| e }
end
assert_equal :test_result, result
@@ -1697,6 +1662,136 @@ class RegistrationTest < Minitest::Test
end
em :test_write_local_inventory
+ def test_write_local_inventory_must_pay
+ low_cust = customer(
+ sgx: @sgx,
+ jid: Blather::JID.new("test\\40onboarding.example.com@proxy")
+ ).with_balance(5.0)
+ high_cust = customer(
+ sgx: @sgx,
+ jid: Blather::JID.new("test\\40onboarding.example.com@proxy")
+ ).with_balance(100.0)
+
+ stub_request(
+ :post,
+ "https://dashboard.bandwidth.com/v1.0/accounts/moveto/moveTns"
+ ).with(
+ body: {
+ CustomerOrderId: "test",
+ SourceAccountId: "bandwidth_account_id",
+ SiteId: "test_site",
+ SipPeerId: "test_peer",
+ TelephoneNumbers: { TelephoneNumber: "5555550000" }
+ }.to_xml(indent: 0, root: "MoveTnsOrder")
+ ).to_return(status: 200, body: "", headers: {})
+
+ Registration::Finish::REDIS.expect(
+ :get,
+ nil,
+ ["jmp_customer_pending_invite-test"]
+ )
+ Registration::Finish::REDIS.expect(
+ :del,
+ nil,
+ ["jmp_customer_pending_invite-test"]
+ )
+ Registration::Finish::REDIS.expect(
+ :hget,
+ nil,
+ ["jmp_group_codes", nil]
+ )
+ Registration::Finish::DB.expect(
+ :exec_defer,
+ EMPromise.resolve(OpenStruct.new(cmd_tuples: 1)),
+ [String, ["+15555550000"]]
+ )
+ Bwmsgsv2Repo::REDIS.expect(
+ :get,
+ EMPromise.resolve(nil),
+ ["jmp_customer_backend_sgx-test"]
+ )
+ Bwmsgsv2Repo::REDIS.expect(
+ :set,
+ nil,
+ [
+ "catapult_fwd-+15555550000",
+ "xmpp:test\\40onboarding.example.com@proxy"
+ ]
+ )
+ Bwmsgsv2Repo::REDIS.expect(
+ :set,
+ nil,
+ ["catapult_fwd_timeout-customer_test@component", 25]
+ )
+
+ local_tel = Minitest::Mock.new(
+ TelSelections::ChooseTel::Tn::LocalInventory.new(
+ TelSelections::ChooseTel::Tn.new("+15555550000"),
+ "bandwidth_account_id",
+ price: 10.0
+ )
+ )
+
+ result = execute_command do
+ local_tel.expect(:charge, EMPromise.reject(:test_result), [Customer])
+ @sgx.expect(
+ :register!,
+ EMPromise.resolve(@sgx.with(
+ registered?: Blather::Stanza::Iq::IBR.new.tap do |ibr|
+ ibr.phone = "+15555550000"
+ end
+ )),
+ ["+15555550000"]
+ )
+
+ Command::COMMAND_MANAGER.expect(
+ :write,
+ EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
+ iq.from = "customer@example.org"
+ iq.form.fields = [
+ { var: "activation_method", value: "credit_card" }
+ ]
+ }),
+ [Matching.new do |iq|
+ assert_equal :form, iq.form.type
+ assert_equal "Purchase Number", iq.form.title
+ end]
+ )
+
+ Command.execution.customer_repo.expect(
+ :find,
+ EMPromise.resolve(high_cust),
+ ["test"]
+ )
+
+ Command::COMMAND_MANAGER.expect(
+ :write,
+ EMPromise.resolve(Blather::Stanza::Iq::Command.new.tap { |iq|
+ iq.from = "customer@example.org"
+ }),
+ [Matching.new do |iq|
+ assert_equal(
+ "Pay by credit card, save, then next here to continue: " \
+ "http://creditcard.example.com?&amount=10",
+ iq.note.text
+ )
+ end]
+ )
+
+ Registration::Finish.new(
+ low_cust,
+ local_tel
+ ).write.catch { |e| e }
+ end
+
+ assert_equal :test_result, result
+ assert_mock @sgx
+ assert_mock Registration::Finish::REDIS
+ assert_mock Bwmsgsv2Repo::REDIS
+ assert_mock Command::COMMAND_MANAGER
+ end
+ em :test_write_local_inventory_must_pay
+
def test_write_tn_fail
create_order = stub_request(
:post,