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