admin_command.rb

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