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