Files
sure/app/helpers/reports_helper.rb
LPW bf9bcae600 Add gains by tax treatment to investment report with grouped subtype dropdown (#701)
* Add tax treatment metrics to reports, forms, and models

- Implement `build_gains_by_tax_treatment` for grouping gains by tax treatment
- Update investment performance view with tax treatment breakdown
- Add tax treatment field to crypto and investments forms
- Introduce `realized_gain_loss` calculation in the Trade model
- Group investment subtypes by region for improved dropdown organization

* Optimize investment performance report by reducing N+1 queries

- Eager-load associations in `build_gains_by_tax_treatment` to minimize database queries
- Preload holdings for realized gain/loss calculations in trades
- Refactor views to standardize "no data" placeholder using translations
- Adjust styling in tax treatment breakdown for improved layout

* Enhance investment performance translations and optimize holdings lookup logic

- Update `holdings_count` and `sells_count` translations to handle pluralization
- Refactor views to use pluralized translation keys with count interpolation
- Optimize preloaded holdings lookup in `Trade` to ensure deterministic selection using `select` and `max_by`

* Refine preloaded holdings logic in `Trade` model

- Treat empty preloaded holdings as authoritative to prevent unnecessary DB queries
- Add explicit fallback behavior for database query when holdings are not preloaded

---------

Co-authored-by: luckyPipewrench <luckypipewrench@proton.me>
2026-01-19 15:44:49 +01:00

49 lines
1.5 KiB
Ruby

module ReportsHelper
# Returns CSS classes for tax treatment badge styling
def tax_treatment_badge_classes(treatment)
case treatment.to_sym
when :tax_exempt
"bg-green-500/10 text-green-600 theme-dark:text-green-400"
when :tax_deferred
"bg-blue-500/10 text-blue-600 theme-dark:text-blue-400"
when :tax_advantaged
"bg-purple-500/10 text-purple-600 theme-dark:text-purple-400"
else
"bg-gray-500/10 text-secondary"
end
end
# Generate SVG polyline points for a sparkline chart
# Returns empty string if fewer than 2 data points (can't draw a line with 1 point)
def sparkline_points(values, width: 60, height: 16)
return "" if values.nil? || values.length < 2 || values.all? { |v| v.nil? || v.zero? }
nums = values.map(&:to_f)
max_val = nums.max
min_val = nums.min
range = max_val - min_val
range = 1.0 if range.zero?
points = nums.each_with_index.map do |val, i|
x = (i.to_f / [ nums.length - 1, 1 ].max) * width
y = height - ((val - min_val) / range * (height - 2)) - 1
"#{x.round(1)},#{y.round(1)}"
end
points.join(" ")
end
# Calculate cumulative net values from trends data
def cumulative_net_values(trends)
return [] if trends.nil?
running = 0
trends.map { |t| running += t[:net].to_i; running }
end
# Check if trends data has enough points for sparklines (need at least 2)
def has_sparkline_data?(trends_data)
trends_data&.length.to_i >= 2
end
end