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