admin_command.rb

  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