diff --git a/app/models/event.rb b/app/models/event.rb index 2fc1f300..fe191078 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -69,7 +69,7 @@ class Event < ActiveRecord::Base validates_associated :organization, :emails, :event_roles, :eventdates validates_format_of :contactemail, :with => Event::EmailRegex, :multiline => true # validate :eventdate_valid? - validate :textable_social_valid? + validate :textable_social_valid?, :check_eventdates_to_be_destroyed scope :current_year, -> { where("representative_date >= ? or last_representative_date > ?", Account.magic_date, Account.magic_date) } @@ -230,4 +230,17 @@ def textable_social_valid? errors.add(:textable_social, "Textable must be enabled if social textable is enabled") end end + + def check_eventdates_to_be_destroyed + # If we are trying to update an event, someone might try to delete an eventdate. + # This is bad if someone has billed for it. There is before_destroy validation, + # and a foreign key check, but because the eventdate is removed from the event, + # it is not automatically validated on submission. This we must manually check + # that we can delete events here. + eventdates.each do |eventdate| + if eventdate.marked_for_destruction? and !eventdate.can_destroy? + errors.add(:eventdates, "Cannot delete an eventdate that has been billed for") + end + end + end end diff --git a/app/models/eventdate.rb b/app/models/eventdate.rb index 31d7824c..d2d8daf3 100644 --- a/app/models/eventdate.rb +++ b/app/models/eventdate.rb @@ -18,6 +18,8 @@ class Eventdate < ApplicationRecord before_validation :prune_roles after_save :synchronize_representative_dates + before_destroy :check_can_destroy + Event_Span_Days = 2; Event_Span_Seconds = Event_Span_Days * 24 * 60 * 60; @@ -63,6 +65,17 @@ def valid_strike? ((strikedate.to_i - enddate.to_i) < Event_Span_Seconds)) end + def can_destroy? + not self.timecard_entries.any? + end + + def check_can_destroy + if not self.can_destroy? + errors.add(:base, "Cannot delete an eventdate that has been billed for") + throw(:abort) + end + end + def has_call? self.calltype == "literal" or self.calltype == "startdate" end diff --git a/app/models/timecard_entry.rb b/app/models/timecard_entry.rb index a2217d85..c180b1c6 100644 --- a/app/models/timecard_entry.rb +++ b/app/models/timecard_entry.rb @@ -1,12 +1,12 @@ class TimecardEntry < ApplicationRecord belongs_to :member - belongs_to :eventdate + belongs_to :eventdate, required: true belongs_to :timecard extend Enumerize enumerize :eventpart, in: ["call", "show", "strike"], default: "show" - validates_presence_of :member_id, :eventdate_id, :hours, :eventpart + validates_presence_of :eventdate, :member_id, :hours, :eventpart validates_numericality_of :hours, :less_than_or_equal_to => 37.5, :greater_than => 0 validates_associated :member validates_inclusion_of :timecard, :in => ->(t){Timecard.valid_timecards}, :message => 'is not a current timecard', :allow_nil => true diff --git a/app/views/events/_eventdate_fields.html.erb b/app/views/events/_eventdate_fields.html.erb index cebfa003..4fa2c39d 100644 --- a/app/views/events/_eventdate_fields.html.erb +++ b/app/views/events/_eventdate_fields.html.erb @@ -108,10 +108,14 @@ <% if can? :tic, @event %>