docs/developer/core-concepts/reports.mdx
Spree provides a flexible reporting system that allows you to generate data exports for sales analytics, product performance, and custom business metrics. Reports are generated asynchronously and delivered as downloadable CSV files.
erDiagram
Report {
string type
string currency
datetime date_from
datetime date_to
bigint store_id
bigint user_id
}
ReportLineItem {
string record
string report
}
Store {
string name
string code
}
AdminUser {
string email
}
GenerateJob {
string report_id
}
Report ||--|| Store : "belongs to"
Report ||--o| AdminUser : "belongs to"
Report ||--o{ ReportLineItem : "generates"
Report ||--|| GenerateJob : "triggers"
Key relationships:
The reporting system uses several design patterns:
Spree::Report and are stored in the same database table with a type columnSpree::ReportLineItem subclasses transform raw records into formatted outputSpree.reports for discovery and validationSpree ships with two built-in reports:
The Sales Total report provides line-item level detail for all completed orders within a date range.
Columns:
date - Order completion dateorder - Order numberproduct - Variant descriptive namequantity - Line item quantitypre_tax_amount - Amount before taxespromo_total - Promotion discounts appliedshipment_total - Shipping coststax_total - Tax amounttotal - Final amount including all adjustmentsThe Products Performance report aggregates sales metrics by product for the specified period.
Columns:
sku - Product SKUname - Product namevendor - Vendor name (if multi-vendor enabled)brand - Brand namecategory_lvl0/1/2 - Category hierarchy from main taxonprice - Current product priceweeks_online - Weeks since product became availablepre_tax_amount - Total pre-tax salestax_total - Total taxes collectedquantity - Total units soldpromo_total - Total promotion discountstotal - Total revenuereport.created event fires via publishes_lifecycle_events concernSpree::ReportSubscriber catches event and enqueues GenerateJobreport.generate:
line_items_scope in batchesReportLineItem| File | Purpose |
|---|---|
core/app/models/spree/report.rb | Base report model |
core/app/models/spree/report_line_item.rb | Base line item presenter |
core/app/models/spree/reports/*.rb | Built-in report implementations |
core/app/models/spree/report_line_items/*.rb | Built-in line item formatters |
core/app/subscribers/spree/report_subscriber.rb | Event subscriber for async generation |
core/app/jobs/spree/reports/generate_job.rb | Background job for CSV creation |
core/app/mailers/spree/report_mailer.rb | Notification emails |
admin/app/controllers/spree/admin/reports_controller.rb | Admin UI controller |
# Returns the scope of records for the report
def line_items_scope
raise NotImplementedError
end
# Returns formatted line items (with optional limit for preview)
def line_items(options = {})
scope = line_items_scope
scope = scope.limit(options[:limit]) if options[:limit].present?
scope.map { |record| line_item_class.new(record: record, report: self) }
end
# Generates the CSV file and handles attachment
def generate
generate_csv
handle_attachment
send_report_done_email
end
# Returns the corresponding line item class
def line_item_class
"Spree::ReportLineItems::#{type.demodulize}".safe_constantize
end
# Returns column headers for display
def self.headers
attribute_types.keys.map do |attribute|
{ name: attribute.to_sym, label: Spree.t(attribute.to_sym) }
end
end
# Returns column names for CSV header row
def self.csv_headers
attribute_types.keys
end
# Converts line item to CSV row array
def to_csv
self.class.attribute_types.keys.map { |attr| send(attr) }
end
Configure the number of preview rows shown in the admin UI:
Spree::Admin::RuntimeConfig.reports_line_items_limit = 100
Reports use a dedicated queue. Configure your job processor:
# Sidekiq example
Spree.queues.reports = :reports
Report access is controlled by CanCanCan. By default, only users with the :manage ability on Spree::Report can access reports. Configure permissions in your permission sets.
# Example: Allow all admins to view reports
can :manage, Spree::Report