summaryrefslogtreecommitdiff
path: root/app/models/target.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/models/target.rb')
-rw-r--r--app/models/target.rb67
1 files changed, 39 insertions, 28 deletions
diff --git a/app/models/target.rb b/app/models/target.rb
index 9211e74..2efd3b2 100644
--- a/app/models/target.rb
+++ b/app/models/target.rb
@@ -1,42 +1,53 @@
-# app/models/target.rb
class Target < ApplicationRecord
- has_many :target_allocations, dependent: :destroy
- has_many :nutrient_profiles, through: :target_allocations
+ include NutrientVector
- accepts_nested_attributes_for :target_allocations, allow_destroy: true
- # validate :percentages_sum_to_100
+ has_many :target_allocations, inverse_of: :target, dependent: :destroy
- def weighted_requirements
- totals = Hash.new(0.0)
- denom = 100.0
+ after_initialize :set_defaults, if: :new_record?
- target_allocations.includes(:nutrient_profile).each do |alloc|
- profile = alloc.nutrient_profile
- next unless profile
+ validate :allocations_sum_to_100
- weight = (alloc.percentage || 0).to_f / denom
- next if weight <= 0
+ # Recompute when allocations change; keep it simple (memoized per instance)
+ def recompute_nutrients!
+ @nutrient_values = nil
+ nutrient_values
+ end
- # Prefer the helper, but gracefully fall back to slicing attributes.
- reqs = if profile.respond_to?(:requirements_hash)
- profile.requirements_hash
- else
- profile.attributes.slice(*NutrientProfile::NUTRIENT_KEYS.map(&:to_s))
- end
+ private
+
+ def nutrient_values
+ @nutrient_values ||= get_nutrient_values
+ end
+
+ def get_nutrient_values
+ sums = Hash.new(0.0)
+ allocs = target_allocations.includes(:nutrient_profile)
- reqs.each do |nutrient_key, value|
- next if value.nil?
- totals[nutrient_key.to_s] += value.to_f * weight
+ allocs.each do |alloc|
+ weight = alloc.percentage.to_f / 100.0
+ profile = alloc.nutrient_profile
+ NutrientVector::NUTRIENT_KEYS.each do |k|
+ sums[k] += profile.public_send(k).to_f * weight
end
end
- totals
+ # Ensure all keys exist, even when there are no allocations
+ NutrientVector::NUTRIENT_KEYS.each { |k| sums[k] ||= 0.0 }
+ sums.freeze
end
- private
+ def set_defaults
+ self.name ||= "Cible #{Date.today + 1.month}"
+ if target_allocations.empty?
+ nutrient_profiles = NutrientProfile.limit(3)
+ nutrient_profiles.each do |profile|
+ target_allocations.build(nutrient_profile: profile, percentage: 0)
+ end
+ end
+ end
- # def percentages_sum_to_100
- # sum = target_allocations.sum { |a| a.percentage.to_f }
- # errors.add(:base, "La somme des pourcentages doit être égale à 100%") unless (sum - 100.0).abs <= 0.1
- # end
+ def allocations_sum_to_100
+ sum = target_allocations.reject(&:marked_for_destruction?).sum { |a| a.percentage.to_f }
+ errors.add(:base, "La somme des pourcentages doit être 100%") unless (sum - 100).abs < 0.01
+ end
end
Copyright 2019--2026 Marius PETER