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