# 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 "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)] ].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