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