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