.rubocop.yml 🔗
@@ -42,6 +42,7 @@ Naming/MethodParameterName:
     - iq
     - db
     - to
+    - tn
 
 Layout/IndentationStyle:
   Enabled: false
  Amolith created
- Add methods necessary for actually assigning numbers to customers and
  deleting those numbers from the local database
- Add accompanying test
Signed-off-by: Amolith <amolith@secluded.site>
  
  
  
.rubocop.yml              |  1 
lib/bandwidth_tn_repo.rb  | 10 ++++
lib/registration.rb       | 14 +----
lib/tel_selections.rb     | 52 +++++++++++++++++++++++-
sgx_jmp.rb                |  2 
test/test_registration.rb | 86 +++++++++++++++++++++++++++++++++++++++++
6 files changed, 151 insertions(+), 14 deletions(-)
@@ -42,6 +42,7 @@ Naming/MethodParameterName:
     - iq
     - db
     - to
+    - tn
 
 Layout/IndentationStyle:
   Enabled: false
  @@ -40,4 +40,14 @@ class BandwidthTnRepo
 			BandwidthIris::Disconnect.create(order_name, tn)
 		end
 	end
+
+	def move(tel, order_name, source_account_id)
+		tn = tel.sub(/\A\+1/, "")
+		BandwidthIris::Tn.new({ telephone_number: tn }, @move_client).move(
+			customer_order_id: order_name,
+			source_account_id: source_account_id,
+			site_id: CONFIG[:bandwidth_site],
+			sip_peer_id: CONFIG[:bandwidth_peer]
+		)
+	end
 end
  @@ -597,16 +597,10 @@ class Registration
 		end
 
 		def write
-			BandwidthTnReservationRepo.new.get(@customer, @tel.tel).then do |rid|
-				BandwidthTNOrder.create(
-					@tel.tel,
-					customer_order_id: @customer.customer_id,
-					reservation_id: rid
-				).then(&:poll).then(
-					->(_) { customer_active_tel_purchased },
-					method(:number_purchase_error)
-				)
-			end
+			@tel.order(DB, @customer).then(
+				->(_) { customer_active_tel_purchased },
+				method(:number_purchase_error)
+			)
 		end
 
 	protected
  @@ -22,6 +22,15 @@ class TelSelections
 		@redis.setex("pending_tel_for-#{jid}", THIRTY_DAYS, tel.pending_value)
 	end
 
+	def set_tel(jid, tel)
+		ChooseTel::Tn::LocalInventory.fetch(tel).then do |local_inv|
+			set(
+				jid,
+				local_inv || ChooseTel::Tn::Bandwidth.new(tel)
+			)
+		end
+	end
+
 	def delete(jid)
 		@redis.del("pending_tel_for-#{jid}")
 	end
@@ -138,7 +147,7 @@ class TelSelections
 							full_number: row["tel"].sub(/\A\+1/, ""),
 							city: row["locality"],
 							state: row["region"]
-						))
+						), row["bandwidth_account_id"])
 					}
 				}
 			end
@@ -205,7 +214,9 @@ class TelSelections
 
 			def self.for_pending_value(value)
 				if value.start_with?("LocalInventory/")
-					LocalInventory.new(Tn.new(value.sub(/\ALocalInventory\//, "")))
+					LocalInventory.new(
+						*Tn.new(value.sub(/\ALocalInventory\//, "")).split("/", 2)
+					)
 				else
 					Bandwidth.new(Tn.new(value))
 				end
@@ -262,16 +273,51 @@ class TelSelections
 				def reserve(customer)
 					BandwidthTnReservationRepo.new.ensure(customer, tel)
 				end
+
+				def order(_, customer)
+					BandwidthTnReservationRepo.new.get(customer, tel).then do |rid|
+						BandwidthTNOrder.create(
+							tel,
+							customer_order_id: customer.customer_id,
+							reservation_id: rid
+						).then(&:poll)
+					end
+				end
 			end
 
 			class LocalInventory < SimpleDelegator
+				def self.fetch(tn, db: DB)
+					db.query_defer("SELECT * FROM tel_inventory WHERE tel = $1", [tn])
+						.then { |rows|
+						rows.first&.then { |row|
+							new(Tn::Option.new(
+								full_number: row["tel"].sub(/\A\+1/, ""),
+								city: row["locality"],
+								state: row["region"]
+							), row["bandwidth_account_id"])
+						}
+					}
+				end
+
+				def initialize(tn, bandwidth_account_id)
+					super(tn)
+					@bandwidth_account_id = bandwidth_account_id
+				end
+
 				def pending_value
-					"LocalInventory/#{tel}"
+					"LocalInventory/#{tel}/#{@bandwidth_account_id}"
 				end
 
 				def reserve(*)
 					EMPromise.resolve(nil)
 				end
+
+				def order(db, customer)
+					BandwidthTnRepo.new.move(
+						tel, customer.customer_id, @bandwidth_account_id
+					)
+					db.exec_defer("DELETE FROM tel_inventory WHERE tel = $1", [tel])
+				end
 			end
 		end
 
  @@ -1019,7 +1019,7 @@ Command.new(
 				cmd.form.fields = [{ var: "to", value: jid }]
 				cmd.form.type = "submit"
 			}).then { |result|
-				TEL_SELECTIONS.set(result.form.field("from")&.value.to_s.strip, tel)
+				TEL_SELECTIONS.set_tel(result.form.field("from")&.value.to_s.strip, tel)
 			}.then { Command.finish }
 		end
 	end
  @@ -1501,6 +1501,92 @@ class RegistrationTest < Minitest::Test
 		end
 		em :test_write_onboarding
 
+		def test_write_local_inventory
+			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(nil),
+				[String, ["+15555550000"]]
+			)
+			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]
+			)
+			result = execute_command do
+				@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.reject(:test_result),
+					[Matching.new do |iq|
+						assert_equal :form, iq.form.type
+						assert iq.form.field("subdomain")
+					end]
+				)
+
+				Registration::Finish.new(
+					customer(
+						sgx: @sgx,
+						jid: Blather::JID.new("test\\40onboarding.example.com@proxy")
+					),
+					TelSelections::ChooseTel::Tn::LocalInventory.new(
+						TelSelections::ChooseTel::Tn.new("+15555550000"),
+						"bandwidth_account_id"
+					)
+				).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
+
 		def test_write_tn_fail
 			create_order = stub_request(
 				:post,