number_change.rb

  1# frozen_string_literal: true
  2
  3require "value_semantics/monkey_patched"
  4require_relative "../admin_action"
  5require_relative "../form_to_h"
  6
  7class AdminAction
  8	class NumberChange < AdminAction
  9		include Isomorphic
 10		class Command
 11			using FormToH
 12
 13			def self.for(target_customer, reply:)
 14				EMPromise.resolve(
 15					new(
 16						customer_id: target_customer.customer_id,
 17						old_tel: target_customer.registered?.phone
 18					)
 19				).then { |x|
 20					reply.call(x.form).then(&x.method(:change))
 21				}
 22			end
 23
 24			def initialize(**bag)
 25				@bag = bag
 26			end
 27
 28			def form
 29				FormTemplate.render("admin_number_change")
 30			end
 31
 32			def change(result)
 33				AdminAction::NumberChange.for(
 34					**@bag,
 35					**result.form.to_h
 36						.reject { |_k, v| v == "nil" }.transform_keys(&:to_sym)
 37				)
 38			end
 39		end
 40
 41		NilKey = Struct.new(:key) {
 42			def to_s
 43				"Expected a key with a value, but #{key} has no value."
 44			end
 45		}
 46
 47		def customer_id
 48			@attributes[:customer_id]
 49		end
 50
 51		def old_tel
 52			@attributes[:old_tel]
 53		end
 54
 55		def new_tel
 56			@attributes[:new_tel]
 57		end
 58
 59		def should_delete?
 60			["1", "true"].include?(@attributes[:should_delete])
 61		end
 62
 63		def check_forward
 64			EMPromise.all([
 65				check_noop,
 66				check_exist
 67			])
 68		end
 69
 70		def forward
 71			sgx = TrivialBackendSgxRepo.new.get(customer_id)
 72			EMPromise.all([
 73				REDIS.rename("catapult_fwd-#{old_tel}", "catapult_fwd-#{new_tel}"),
 74				sgx.register!(new_tel),
 75				should_delete? && first_time? ? disconnect_number : nil
 76			]).then { self }
 77		end
 78
 79		def to_reverse
 80			with(
 81				old_tel: new_tel,
 82				new_tel: old_tel
 83			)
 84		end
 85
 86		def to_s
 87			"number_change(#{customer_id}): #{old_tel} -> #{new_tel}#{delete_warning}"
 88		end
 89
 90	protected
 91
 92		def disconnect_number
 93			# Order name is limited to 40 characters
 94			# Assuming 12 chars for new_tel and 12 for customer_id, this is tight
 95			# but ok
 96			BandwidthTnRepo.new.disconnect(
 97				old_tel,
 98				"cust #{customer_id} swap to #{new_tel}"
 99			)
100		end
101
102		def delete_warning
103			return "" unless should_delete? && !first_time?
104
105			" * NOT DELETING"
106		end
107
108		def check_noop
109			EMPromise.reject(NoOp.new) if new_tel == old_tel
110		end
111
112		def check_exist
113			cat_jid = "catapult_jid-#{old_tel}"
114			REDIS.exists(cat_jid).then { |v|
115				EMPromise.reject(NilKey.new(cat_jid)) unless v == 1
116			}
117		end
118	end
119end