mirror of
https://github.com/Growstuff/growstuff.git
synced 2026-10-31 03:09:06 -04:00
- Removed unused styles and helper methods from _garden_layout.scss, _homepage.scss, and overrides.scss. - Updated _home_dashboard.scss to enhance button styles and added new harvest picker styles. - Introduced HarvestPicker component for improved harvest recording functionality. - Refactored home dashboard views to utilize new home_section helper for consistent layout. - Simplified and optimized existing methods in application_helper.rb, activity.rb, and harvest.rb. - Removed deprecated homepage_records methods from Activity and Harvest models. - Updated tests to reflect changes in helper methods and removed obsolete tests.
187 lines
5.1 KiB
Ruby
187 lines
5.1 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class Harvest < ApplicationRecord
|
|
include ActionView::Helpers::NumberHelper
|
|
extend FriendlyId
|
|
include PhotoCapable
|
|
include Ownable
|
|
include Likeable
|
|
|
|
attr_accessor :overall_rating
|
|
|
|
friendly_id :harvest_slug, use: %i(slugged finders)
|
|
|
|
# Constants
|
|
UNITS_VALUES = {
|
|
"individual" => "individual",
|
|
"bunches" => "bunch",
|
|
"sprigs" => "sprig",
|
|
"handfuls" => "handful",
|
|
"litres" => "litre",
|
|
"pints" => "pint",
|
|
"quarts" => "quart",
|
|
"buckets" => "bucket",
|
|
"baskets" => "basket",
|
|
"bushels" => "bushel"
|
|
}.freeze
|
|
|
|
WEIGHT_UNITS_VALUES = {
|
|
"kg" => "kg",
|
|
"lb" => "lb",
|
|
"oz" => "oz"
|
|
}.freeze
|
|
|
|
# Exact definitions of the international avoirdupois units, in kilograms.
|
|
KG_PER_WEIGHT_UNIT = {
|
|
"kg" => BigDecimal("1"),
|
|
"lb" => BigDecimal("0.45359237"),
|
|
"oz" => BigDecimal("0.028349523125")
|
|
}.freeze
|
|
|
|
##
|
|
## Triggers
|
|
after_validation :cleanup_quantities
|
|
before_save :set_si_weight
|
|
|
|
##
|
|
## Relationships
|
|
belongs_to :crop, counter_cache: true
|
|
belongs_to :plant_part, counter_cache: true
|
|
belongs_to :planting, optional: true, counter_cache: true
|
|
|
|
##
|
|
## Scopes
|
|
scope :interesting, -> { has_photos.one_per_owner }
|
|
scope :recent, -> { order(created_at: :desc) }
|
|
scope :one_per_owner, lambda {
|
|
joins("JOIN members m ON (m.id=harvests.owner_id)
|
|
LEFT OUTER JOIN harvests h2
|
|
ON (m.id=h2.owner_id AND harvests.id < h2.id)").where("h2 IS NULL")
|
|
}
|
|
|
|
delegate :name, :slug, to: :crop, prefix: true
|
|
delegate :login_name, :slug, to: :owner, prefix: true
|
|
delegate :name, to: :plant_part, prefix: true
|
|
|
|
##
|
|
## Validations
|
|
validates :crop, approved: true
|
|
validates :crop, presence: { message: :crop_not_found }
|
|
validates :plant_part, presence: { message: :crop_not_found }
|
|
validates :harvested_at, presence: true
|
|
validates :quantity, allow_nil: true, numericality: {
|
|
only_integer: false, greater_than_or_equal_to: 0
|
|
}
|
|
validates :unit, allow_blank: true, inclusion: {
|
|
in: UNITS_VALUES.values, message: :not_a_valid_unit
|
|
}
|
|
validates :weight_quantity, allow_nil: true, numericality: { only_integer: false }
|
|
validates :weight_unit, allow_blank: true, inclusion: {
|
|
in: WEIGHT_UNITS_VALUES.values, message: :not_a_valid_unit
|
|
}
|
|
validate :crop_must_match_planting
|
|
validate :owner_must_match_planting
|
|
validate :harvest_must_be_after_planting
|
|
|
|
def time_from_planting_to_harvest
|
|
return if planting.blank?
|
|
|
|
harvested_at - planting.planted_at
|
|
end
|
|
|
|
def default_photo
|
|
most_liked_photo || planting&.default_photo
|
|
end
|
|
|
|
# we're storing the harvest weight in kilograms in the db too
|
|
# to make data manipulation easier
|
|
def set_si_weight
|
|
return if weight_unit.nil?
|
|
|
|
self.si_weight = (weight_quantity * KG_PER_WEIGHT_UNIT.fetch(weight_unit)).round(3).to_f
|
|
end
|
|
|
|
def cleanup_quantities
|
|
self.quantity = nil if quantity&.zero?
|
|
self.unit = nil if quantity.blank?
|
|
self.weight_quantity = nil if weight_quantity&.zero?
|
|
self.weight_unit = nil if weight_quantity.blank?
|
|
end
|
|
|
|
def harvest_slug
|
|
"#{owner.login_name}-#{crop}".downcase.tr(' ', '-')
|
|
end
|
|
|
|
# stringify as "beet in Skud's backyard" or similar
|
|
def to_s
|
|
# 50 individual apples, weighing 3lb
|
|
# 2 buckets of apricots, weighing 10kg
|
|
@to_s ||= "#{quantity_to_human} #{unit_to_human} #{crop_name_to_human} #{weight_to_human}".strip
|
|
end
|
|
|
|
def quantity_to_human
|
|
@quantity_to_human ||= if quantity
|
|
number_to_human(quantity.to_s, strip_insignificant_zeros: true)
|
|
else
|
|
""
|
|
end
|
|
end
|
|
|
|
def unit_to_human
|
|
@unit_to_human ||= begin
|
|
if !quantity || !unit
|
|
""
|
|
elsif unit == 'individual'
|
|
'individual'
|
|
elsif quantity == 1
|
|
"#{unit} of"
|
|
else
|
|
"#{unit.pluralize} of"
|
|
end
|
|
end
|
|
end
|
|
|
|
def weight_to_human
|
|
@weight_to_human ||= if weight_quantity
|
|
"weighing #{number_to_human(weight_quantity, strip_insignificant_zeros: true)} #{weight_unit}"
|
|
else
|
|
""
|
|
end
|
|
end
|
|
|
|
def crop_name_to_human
|
|
@crop_name_to_human ||= begin
|
|
if unit != 'individual' # buckets of apricot*s*
|
|
crop.name.pluralize
|
|
elsif quantity == 1
|
|
crop.name
|
|
else
|
|
crop.name.pluralize
|
|
end.to_s
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def crop_must_match_planting
|
|
return if planting.blank? # only check if we are linked to a planting
|
|
|
|
errors.add(:planting, :same_crop_required) unless crop == planting.crop
|
|
end
|
|
|
|
def owner_must_match_planting
|
|
return if planting.blank? # only check if we are linked to a planting
|
|
|
|
return if owner == planting.owner || planting.garden.garden_collaborators.where(member_id: owner).any?
|
|
|
|
errors.add(:owner, :same_owner_required)
|
|
end
|
|
|
|
def harvest_must_be_after_planting
|
|
# only check if we are linked to a planting
|
|
return unless harvested_at.present? && planting.present? && planting.planted_at.present?
|
|
|
|
errors.add(:planting, :harvest_after_planted) unless harvested_at > planting.planted_at
|
|
end
|
|
end
|