class Timesheet < ActiveRecord::Base attr_accessible :status, :user_id, :start_date, :end_date, :activities_attributes SUBMITTED = 'Submitted' APPROUVED = 'Approuved' REJECTED = 'Rejected' STATUS_VALUES = [SUBMITTED, APPROUVED, REJECTED] belongs_to :user has_many :activities, dependent: :destroy, inverse_of: :timesheet has_many :time_entries, through: :activities accepts_nested_attributes_for :activities, allow_destroy: true validates :user_id, presence: true validates :status, presence: true, inclusion: {in: STATUS_VALUES} validate :maximum_worktime_per_day after_update :check_an_activity_present after_initialize :init_working_week def date_range (start_date..end_date).to_a end def total_worked_time days = 0 days = time_entries.sum(:worktime) unless time_entries.empty? days end def create_activity_days(activity) date_range.each { |date| activity.time_entries.build(workdate: date) } end def build_and_sort_time_entries entries = [] activities.each do |activity| date_range.each do |week_day| activity.time_entries.build(workdate: week_day) unless activity.worked_days.include?(week_day) end entries = activity.time_entries entries.sort! { |a, b| a.workdate <=> b.workdate } end entries end private def init_working_week if start_date.blank? || end_date.blank? set_start_and_end_dates end end def set_start_and_end_dates filter_date = Date.today last_timesheet = Timesheet.last filter_date = last_timesheet.start_date.next_week if last_timesheet self.start_date = filter_date.beginning_of_week self.end_date = filter_date.end_of_week end def check_an_activity_present raise "You should have at least ONE activity present" if activities.empty? end def maximum_worktime_per_day time_entries_by_date = time_entries.group_by(&:workdate) time_entries_by_date.each do |key, value| errors[:base] << "Maximum daily time should not exceed 1 day" if worktime_by_date(value) > 1 break end end def worktime_by_date(daily_entries) time = 0 time = daily_entries.map(&:worktime).inject(:+) unless daily_entries.empty? time end end