diff --git a/app/models/user_working_hours.rb b/app/models/user_working_hours.rb index 013db8c2eff3..922d0c132600 100644 --- a/app/models/user_working_hours.rb +++ b/app/models/user_working_hours.rb @@ -38,14 +38,12 @@ class UserWorkingHours < ApplicationRecord belongs_to :user, inverse_of: :working_hours validates :valid_from, presence: true, uniqueness: { scope: :user_id } - validates :monday_hours, :tuesday_hours, :wednesday_hours, :thursday_hours, :friday_hours, :saturday_hours, :sunday_hours, - presence: true, - numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 24 } validates :availability_factor, presence: true, numericality: { only_integer: true, greater_than_or_equal_to: 0, less_than_or_equal_to: 100 } validate :at_least_one_working_day_selected + validate :working_day_hours_present_and_in_range scope :for_user, ->(user) { where(user:) } @@ -72,7 +70,7 @@ def self.current DAYS.each do |day| define_method("#{day}_hours") do - (public_send(day) / 60.0).round(2) + ((public_send(day) || 0) / 60.0).round(2) end define_method("#{day}_hours=") do |value| @@ -158,8 +156,21 @@ def abbr_day_name(day) end def at_least_one_working_day_selected - if DAYS.all? { |day| public_send(day).zero? } + if DAYS.all? { |day| public_send(day).to_i.zero? } errors.add(:days, :no_working_day) end end + + def working_day_hours_present_and_in_range + DAYS.each do |day| + minutes = public_send(day) + attr = :"#{day}_hours" + + if minutes.nil? + errors.add(attr, :blank) + elsif minutes.negative? || minutes > 24 * 60 + errors.add(attr, :less_than_or_equal_to, count: 24) + end + end + end end diff --git a/spec/models/user_working_hours_spec.rb b/spec/models/user_working_hours_spec.rb index e5b1c5a42c7e..55bb86720233 100644 --- a/spec/models/user_working_hours_spec.rb +++ b/spec/models/user_working_hours_spec.rb @@ -74,6 +74,26 @@ .is_greater_than_or_equal_to(0) .is_less_than_or_equal_to(100) end + + describe "with a nil weekday column (e.g. omitted from a create payload)" do + it "is invalid rather than raising when a single weekday is nil" do + subject.public_send(:wednesday=, nil) + + expect { subject.valid? }.not_to raise_error + expect(subject).not_to be_valid + expect(subject.errors[:wednesday_hours]).to be_present + end + + it "is invalid rather than raising when every weekday is nil" do + %i[monday tuesday wednesday thursday friday saturday sunday].each do |day| + subject.public_send(:"#{day}=", nil) + end + + expect { subject.valid? }.not_to raise_error + expect(subject).not_to be_valid + expect(subject.errors[:days]).to be_present + end + end end describe "hours accessors" do @@ -85,6 +105,11 @@ working_hours.public_send("#{day}=", 150) expect(working_hours.public_send("#{day}_hours")).to eq(2.5) end + + it "returns 0.0 rather than raising when the underlying minutes column is nil" do + working_hours.public_send("#{day}=", nil) + expect(working_hours.public_send("#{day}_hours")).to eq(0.0) + end end describe "##{day}_hours=" do