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