module Ecom module Core class TaskStep < ApplicationRecord include Filterable before_save :update_task_progress scope :filter_by_condition, ->(condition) { where(condition) } validates :name, :total_contribution_percentage_to_task, presence: true validates_with DateRangeValidator validate :date_range_validator validates_numericality_of :total_contribution_percentage_to_task, greater_than: 0, less_than_or_equal_to: 100 validate :task_step_percentage_validator, on: :create validate :task_step_in_task_template_inclusion_validator belongs_to :task has_many :dependent_task_steps, class_name: 'Ecom::Core::TaskStepDependency', foreign_key: 'dependent_task_step_id' has_many :dependee_task_steps, class_name: 'Ecom::Core::TaskStepDependency', foreign_key: 'dependee_task_step_id' def date_range_validator task_ = Ecom::Core::Task.find_by(id: task_id) return if task_.nil? if !start_date.nil? && start_date < task_.start_date errors.add(:start_date, "The task steps start date can not be before the task's start date") end return unless !end_date.nil? && end_date > task_.end_date errors.add(:end_date, "The task steps end date can not be after the task's end date") end def task_step_percentage_validator return if task_id.nil? task = Ecom::Core::Task.find_by(id: task_id) return if task.nil? total_contribution_of_all_task_steps = task.task_steps.sum(:total_contribution_percentage_to_task) max_total_contribution = 100 - total_contribution_of_all_task_steps return unless total_contribution_percentage_to_task > max_total_contribution errors .add(:total_contribution_of_all_task_steps, "The maximum that this task step can contribute to the total task is #{max_total_contribution}") end def update_task_progress return unless completed_changed? && completed == true # update the task progress task = self.task percent_completed = task.percent_completed task.percent_completed = (percent_completed + total_contribution_percentage_to_task).to_i task.save end def task_step_in_task_template_inclusion_validator return if task_id.nil? task = Ecom::Core::Task.find_by(id: task_id) return if task.nil? task_template = task.task_template return unless task_template.task_steps.nil? errors.add(:base, 'Task steps are not defined for the given task in the task template, please first define the task steps in the task template.') end end end end