# frozen_string_literal: true
require_relative "admin_action_repo"
require_relative "admin_actions/add_invites"
require_relative "admin_actions/cancel"
require_relative "admin_actions/financial"
require_relative "admin_actions/reset_declines"
require_relative "admin_actions/set_trust_level"
require_relative "admin_actions/number_change"
require_relative "bill_plan_command"
require_relative "customer_info_form"
require_relative "financial_info"
require_relative "form_template"
class AdminCommand
def self.for(
target_customer,
customer_repo,
admin_action_repo=AdminActionRepo.new
)
if target_customer
new(target_customer, customer_repo, admin_action_repo)
else
NoUser.new(customer_repo, admin_action_repo, notice: "Customer Not Found")
end
end
class NoUser < AdminCommand
def initialize(
customer_repo,
admin_action_repo=AdminActionRepo.new,
notice: nil
)
@customer_repo = customer_repo
@admin_action_repo = admin_action_repo
@notice = notice
end
def start(command_action=:execute)
return Command.finish(@notice || "Done") if command_action == :complete
reply(
FormTemplate.render("customer_picker", notice: @notice)
).then { |response|
new_context(response.form.field("q").value, response.action)
}
end
end
def initialize(
target_customer,
customer_repo,
admin_action_repo=AdminActionRepo.new
)
@target_customer = target_customer
@customer_repo = customer_repo
@admin_action_repo = admin_action_repo
end
def start(command_action=:execute)
AdminInfo.for(@target_customer).then { |info|
if command_action == :complete
Command.finish { |iq| iq.command << info.form }
else
reply(info.form)
end
}.then { |response| menu_or_done(response.action) }
end
def reply(form)
Command.reply { |reply|
reply.allowed_actions = [:next, :complete]
reply.command << form
}
end
def menu_or_done(command_action=:execute, notice: nil)
return Command.finish("Done") if command_action == :complete
reply(FormTemplate.render("admin_menu", notice: notice)).then do |response|
if response.form.field("action")
handle(response.form.field("action").value, response.action)
end
end
end
def handle(action, command_action)
if respond_to?("action_#{action}")
send("action_#{action}").then do |notice|
menu_or_done(command_action, notice: notice)
end
else
new_context(action)
end
end
def new_context(q, command_action=:execute)
CustomerInfoForm.new(@customer_repo)
.parse_something(q).then do |new_customer|
AdminCommand.for(new_customer, @customer_repo, @admin_action_repo)
.then { |ac| ac.start(command_action) }
end
end
def action_info
# Refresh the data
new_context(@target_customer.customer_id)
end
def action_bill_plan
BillPlanCommand.for(@target_customer).call
end
class Undoable
def initialize(klass)
@klass = klass
end
def call(customer, admin_action_repo:, **)
@klass.for(customer, reply: method(:reply)).then { |action|
Command.customer.then { |actor|
action.with(actor_id: actor.customer_id).perform.then do |performed|
admin_action_repo.create(performed)
end
}
}.then { |action| "Action #{action.id}: #{action}" }
end
def reply(form=nil, note_type: nil, note_text: nil)
Command.reply { |reply|
reply.allowed_actions = [:next, :complete]
reply.command << form if form
reply.note_type = note_type if note_type
reply.note_text = note_text if note_text
}
end
end
class Simple
def initialize(klass)
@klass = klass
end
def call(customer_id, customer_repo:, **)
@klass.call(
customer_id,
reply: method(:reply),
customer_repo: customer_repo
).then { nil }
end
def reply(form=nil, note_type: nil, note_text: nil)
Command.reply { |reply|
reply.allowed_actions = [:next, :complete]
reply.command << form if form
reply.note_type = note_type if note_type
reply.note_text = note_text if note_text
}
end
end
class Undo
def self.for(target_customer, **)
AdminActionRepo.new
.find(1, customer_id: target_customer.customer_id)
.then { |actions|
raise "No actions found" if actions.empty?
actions.first.undo
}
end
end
[
[:cancel_account, Simple.new(AdminAction::CancelCustomer)],
[:financial, Simple.new(AdminAction::Financial)],
[:undo, Undoable.new(Undo)],
[:reset_declines, Undoable.new(AdminAction::ResetDeclines::Command)],
[:set_trust_level, Undoable.new(AdminAction::SetTrustLevel::Command)],
[:add_invites, Undoable.new(AdminAction::AddInvites::Command)],
[:number_change, Undoable.new(AdminAction::NumberChange::Command)]
].each do |action, handler|
define_method("action_#{action}") do
handler.call(
@target_customer,
admin_action_repo: @admin_action_repo,
customer_repo: @customer_repo
)
end
end
end