Class: LcpRuby::Export::ExportHandler

Inherits:
LcpRuby::Events::HandlerBase show all
Defined in:
lib/lcp_ruby/export/export_handler.rb

Overview

Built-in event handler for the export dialog_submit event. Receives the export_config virtual model, builds the query, generates the file.

Instance Attribute Summary

Attributes inherited from LcpRuby::Events::HandlerBase

#changes, #context, #current_user, #event_name, #record, #request_params

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from LcpRuby::Events::HandlerBase

async?, #initialize

Constructor Details

This class inherits a constructor from LcpRuby::Events::HandlerBase

Class Method Details

.handles_eventObject



6
7
8
# File 'lib/lcp_ruby/export/export_handler.rb', line 6

def self.handles_event
  "dialog_submit"
end

Instance Method Details

#callObject



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/lcp_ruby/export/export_handler.rb', line 10

def call
  source_presenter_name = request_params["source_presenter"] || (record.respond_to?(:source_presenter) ? record.source_presenter : nil)
  return failure(I18n.t("lcp_ruby.export.errors.missing_source_presenter",
                        default: "Missing source_presenter parameter")) unless source_presenter_name.present?

  @presenter = LcpRuby.loader.presenter_definition(source_presenter_name)
  @model_definition = LcpRuby.loader.model_definition(@presenter.model)
  @model_class = LcpRuby.registry.model_for(@presenter.model)

  perm_def = LcpRuby.loader.permission_definition(@presenter.model)
  @evaluator = Authorization::PermissionEvaluator.new(perm_def, current_user, @presenter.model)

  return failure(I18n.t("lcp_ruby.export.errors.not_authorized",
                        default: "Not authorized to export")) unless @evaluator.can?(:index)
  return failure(I18n.t("lcp_ruby.export.errors.action_not_authorized",
                        default: "Not authorized to execute export action")) unless @evaluator.can_execute_action?(:export)
  return failure(I18n.t("lcp_ruby.export.errors.not_enabled",
                        default: "Export not enabled for this presenter")) unless @presenter.export_enabled?

  selected = parse_selected_fields
  return failure(I18n.t("lcp_ruby.export.errors.no_fields",
                        default: "No fields selected")) if selected.empty?

  format = (record.respond_to?(:format) ? record.format : "csv").to_s
  format = "csv" unless %w[csv xlsx].include?(format)

  scope = build_scope
  count = scope.count

  max = @presenter.export_max_records
  if count > max
    return failure(
      I18n.t("lcp_ruby.export.too_many_records",
              count: count, max: max,
              default: "Export limited to %{max} records (%{count} matched). Apply filters to narrow down.")
    )
  end

  scope = apply_eager_loading(scope, selected)
  scope = apply_virtual_columns(scope, selected)
  records = scope.limit(max).to_a

  file_data, content_type, extension = generate_file(records, selected, format)
  filename = build_filename(extension)

  save_profile_if_requested(selected, format)
  save_history_if_enabled(selected, format, records.size, file_data)

  Actions::Result.new(
    type: :file_download,
    success: true,
    message: I18n.t("lcp_ruby.export.success", count: records.size, default: "Exported %{count} records"),
    data: { file_data: file_data, filename: filename, content_type: content_type },
    errors: []
  )
rescue LcpRuby::Error => e
  failure(e.message)
rescue StandardError => e
  raise unless Rails.env.production?

  LcpRuby.record_error(e, subsystem: "export", presenter: @presenter&.name, model: @presenter&.model)
  failure(I18n.t("lcp_ruby.export.errors.generic_failure",
                 reason: e.message,
                 default: "Export failed: %{reason}"))
end