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