module Ecom module Core class AttendanceSheet < ApplicationRecord validates :date, presence: true, uniqueness: { scope: :project_id } validates :status, inclusion: StatusConstants::STATUSES belongs_to :project has_many :attendance_sheet_entries has_many :crew_times, through: :attendance_sheet_entries scope :by_project, ->(id) { where(project_id: id) } scope :by_date, ->(date) { where(date: date) } scope :by_status, ->(status) { where(status: status) } scope :by_date_between, ->(from, to) { where('date BETWEEN ? AND ?', from, to) } def self.open_for_date(date, project_id) AttendanceSheet.find_by(status: StatusConstants::OPEN, date: date, project_id: project_id) end def self.open_exists?(project_id) AttendanceSheet .by_project(project_id) .by_status(StatusConstants::OPEN) .exists? end def self.exists_for_today?(project_id) AttendanceSheet .by_project(project_id) .by_date(Date.today) .exists? end def self.open_exists_for_today?(project_id) AttendanceSheet .by_project(project_id) .by_date(Date.today) .by_status(StatusConstants::OPEN) .exists? end # Attendance sheet should be created using the # method below only. This is because we need to # check if there is an open attendance already, # and also that we have only one attendace sheet # per day. def self.create_current(project_id) raise 'Attendance sheet already created for the day.' if AttendanceSheet.exists_for_today?(project_id) if AttendanceSheet.open_exists?(project_id) raise 'There is an open attendance sheet which needs to be submitted before creating a new one.' end AttendanceSheet.create(date: Date.today, opened_at: Time.now, status: StatusConstants::OPEN, project_id: project_id) end def self.submit_current(project_id) sheet = AttendanceSheet.find_by(date: Date.today, status: StatusConstants::OPEN, project_id: project_id) raise 'There is no open attendance sheet to submit.' if sheet.nil? sheet.submitted_at = DateTime.now sheet.status = StatusConstants::SUBMITTED sheet.save sheet end # This method should be used by privileged users # to submit the attendance sheet after the date has # passed. Normally, timekeepers need to open and close # an attendance sheet of a date on the specific date. def self.submit(date, project_id) sheet = AttendanceSheet.open_for_date(date, project_id) raise 'There is no open attendance sheet to submit for the selected day.' unless sheet sheet.submitted_at = DateTime.now sheet.status = StatusConstants::SUBMITTED sheet.save sheet end def submit raise 'Attendance sheet is not open and cannot be submitted' if status != StatusConstants::OPEN self.submitted_at = DateTime.now self.status = StatusConstants::SUBMITTED save end def approve raise 'Attendance sheet is not submitted and cannot be approved' unless status == StatusConstants::SUBMITTED self.status = StatusConstants::APPROVED self.approved_at = DateTime.now save end end end end