1# frozen_string_literal: true
2
3require_relative "admin_action_repo"
4require_relative "admin_actions/add_invites"
5require_relative "admin_actions/add_transaction"
6require_relative "admin_actions/cancel"
7require_relative "admin_actions/financial"
8require_relative "admin_actions/launch_snikket"
9require_relative "admin_actions/number_change"
10require_relative "admin_actions/register_with_sgx"
11require_relative "admin_actions/reset_declines"
12require_relative "admin_actions/set_trust_level"
13require_relative "bill_plan_command"
14require_relative "customer_info_form"
15require_relative "financial_info"
16require_relative "form_template"
17
18class AdminCommand
19 def self.for(
20 target_customer,
21 customer_repo,
22 admin_action_repo=AdminActionRepo.new,
23 snikket_repo=Snikket::Repo.new
24 )
25 if target_customer
26 new(target_customer, customer_repo, admin_action_repo, snikket_repo)
27 else
28 NoUser.new(customer_repo, admin_action_repo, notice: "Customer Not Found")
29 end
30 end
31
32 class NoUser < AdminCommand
33 def initialize(
34 customer_repo,
35 admin_action_repo=AdminActionRepo.new,
36 snikket_repo=Snikket::Repo.new,
37 notice: nil
38 )
39 @customer_repo = customer_repo
40 @admin_action_repo = admin_action_repo
41 @snikket_repo = snikket_repo
42 @notice = notice
43 end
44
45 def start(command_action=:execute)
46 return Command.finish(@notice || "Done") if command_action == :complete
47
48 reply(
49 FormTemplate.render("customer_picker", notice: @notice)
50 ).then { |response|
51 new_context(response.form.field("q").value, response.action)
52 }
53 end
54 end
55
56 def initialize(
57 target_customer,
58 customer_repo,
59 admin_action_repo=AdminActionRepo.new,
60 snikket_repo=Snikket::Repo.new
61 )
62 @target_customer = target_customer
63 @customer_repo = customer_repo || (raise "No cutomer repo")
64 @admin_action_repo = admin_action_repo || (raise "No admin action repo")
65 @snikket_repo = snikket_repo || (raise "No snikket repo")
66 end
67
68 def start(command_action=:execute)
69 AdminInfo.for(@target_customer).then { |info|
70 if command_action == :complete
71 Command.finish { |iq| iq.command << info.form }
72 else
73 reply(info.form)
74 end
75 }.then { |response| menu_or_done(response.action) }
76 end
77
78 def reply(form)
79 Command.reply { |reply|
80 reply.allowed_actions = [:next, :complete]
81 reply.command << form
82 }
83 end
84
85 def menu_or_done(command_action=:execute, notice: nil)
86 return Command.finish("Done") if command_action == :complete
87
88 reg = @target_customer.registered?
89 vars = { notice: notice, customer_id: @target_customer.customer_id,
90 jid: @target_customer.jid, tel: reg ? reg.phone : nil }
91 reply(FormTemplate.render("admin_menu", **vars)).then do |response|
92 if response.form.field("action")
93 handle(response.form.field("action").value, response.action)
94 end
95 end
96 end
97
98 def handle(action, command_action)
99 if respond_to?("action_#{action}")
100 send("action_#{action}").then do |notice|
101 menu_or_done(command_action, notice: notice)
102 end
103 else
104 new_context(action)
105 end
106 end
107
108 def new_context(q, command_action=:execute)
109 CustomerInfoForm.new(@customer_repo)
110 .parse_something(q).then do |new_customer|
111 AdminCommand.for(
112 new_customer,
113 @customer_repo,
114 @admin_action_repo,
115 @snikket_repo
116 ).then { |ac| ac.start(command_action) }
117 end
118 end
119
120 def action_info
121 # Refresh the data
122 new_context(@target_customer.customer_id)
123 end
124
125 def action_bill_plan
126 BillPlanCommand.for(@target_customer).call
127 end
128
129 class Undoable
130 def initialize(klass)
131 @klass = klass
132 end
133
134 def call(customer, admin_action_repo:, **)
135 @klass.for(customer, reply: method(:reply)).then { |action|
136 Command.customer.then { |actor|
137 action.with(actor_id: actor.customer_id).perform.then do |performed|
138 admin_action_repo.create(performed)
139 end
140 }
141 }.then { |action| "Action #{action.id}: #{action}" }
142 end
143
144 def reply(form=nil, note_type: nil, note_text: nil)
145 Command.reply { |reply|
146 reply.allowed_actions = [:next, :complete]
147 reply.command << form if form
148 reply.note_type = note_type if note_type
149 reply.note_text = note_text if note_text
150 }
151 end
152 end
153
154 class Simple
155 def initialize(klass)
156 @klass = klass
157 end
158
159 def call(customer_id, customer_repo:, snikket_repo:, **)
160 @klass.call(
161 customer_id,
162 reply: method(:reply),
163 customer_repo: customer_repo,
164 snikket_repo: snikket_repo
165 ).then { nil }
166 end
167
168 def reply(form=nil, note_type: nil, note_text: nil)
169 Command.reply { |reply|
170 reply.allowed_actions = [:next, :complete]
171 reply.command << form if form
172 reply.note_type = note_type if note_type
173 reply.note_text = note_text if note_text
174 }
175 end
176 end
177
178 class Undo
179 def self.for(target_customer, **)
180 AdminActionRepo.new
181 .find(1, customer_id: target_customer.customer_id)
182 .then { |actions|
183 raise "No actions found" if actions.empty?
184
185 actions.first.undo
186 }
187 end
188 end
189
190 [
191 [:cancel_account, Simple.new(AdminAction::CancelCustomer)],
192 [:financial, Simple.new(AdminAction::Financial)],
193 [:undo, Undoable.new(Undo)],
194 [:reset_declines, Undoable.new(AdminAction::ResetDeclines::Command)],
195 [:set_trust_level, Undoable.new(AdminAction::SetTrustLevel::Command)],
196 [:add_invites, Undoable.new(AdminAction::AddInvites::Command)],
197 [:number_change, Undoable.new(AdminAction::NumberChange::Command)],
198 [:add_transaction, Undoable.new(AdminAction::AddTransaction::Command)],
199 [:launch_snikket, Simple.new(AdminAction::LaunchSnikket)],
200 [:register_with_sgx, Simple.new(AdminAction::RegisterWithSgx)]
201 ].each do |action, handler|
202 define_method("action_#{action}") do
203 handler.call(
204 @target_customer,
205 admin_action_repo: @admin_action_repo,
206 customer_repo: @customer_repo,
207 snikket_repo: @snikket_repo
208 )
209 end
210 end
211end