Files
eminuxCRM/app/models/task.rb
T
eminuxandCursor c4e5f289cf
CI / scan_ruby (push) Failing after 11m20s
CI / scan_js (push) Successful in 10m35s
CI / lint (push) Has been cancelled
Commit iniziale di eminuxCRM: CRM Rails con pipeline, campagne email e Docker.
Include autenticazione, progetti isolati, mail marketing HTML con SMTP, test A/B e editor WYSIWYG.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-17 23:01:48 +02:00

105 lines
2.9 KiB
Ruby

class Task < ApplicationRecord
include Auditable
belongs_to :organization
belongs_to :contact, optional: true
belongs_to :opportunity, optional: true
belongs_to :assigned_user, class_name: "User", optional: true
validates :title, :due_at, presence: true
validates :priority, inclusion: { in: Catalog::TASK_PRIORITIES.keys }
validates :task_type, inclusion: { in: Catalog::TASK_TYPES.keys }
validates :status, inclusion: { in: Catalog::TASK_STATUSES.keys }
scope :pending, -> { where(status: "pending") }
scope :completed, -> { where(status: "completed") }
scope :overdue, -> { pending.where("due_at < ?", Time.zone.now.beginning_of_day) }
scope :due_today, -> { pending.where(due_at: Time.zone.now.all_day) }
scope :upcoming, ->(days = 7) {
pending.where(due_at: Time.zone.now.tomorrow.beginning_of_day..(Time.zone.now + days.days).end_of_day)
}
scope :ordered, -> { order(Arel.sql("CASE priority WHEN 'urgent' THEN 0 WHEN 'high' THEN 1 WHEN 'normal' THEN 2 ELSE 3 END"), :due_at) }
scope :for_project, ->(project) {
return none if project.nil?
where(
id: left_joins(:opportunity)
.joins("INNER JOIN organization_projects ON organization_projects.organization_id = tasks.organization_id")
.where(
"organization_projects.project_id = :pid OR opportunities.project_id = :pid",
pid: project.id
)
.select("tasks.id")
.distinct
)
}
def priority_label
Catalog.label_for(Catalog::TASK_PRIORITIES, priority)
end
def task_type_label
Catalog.label_for(Catalog::TASK_TYPES, task_type)
end
def status_label
Catalog.label_for(Catalog::TASK_STATUSES, status)
end
def overdue?
pending? && due_at < Time.zone.now.beginning_of_day
end
def due_today?
pending? && due_at.to_date == Time.zone.today
end
def pending?
status == "pending"
end
def completed?
status == "completed"
end
def complete!(user: Current.user, create_activity: true)
return false unless pending?
transaction do
update!(status: "completed", completed_at: Time.current, updated_by: user)
create_completion_activity!(user) if create_activity && user
end
true
end
private
def create_completion_activity!(user)
activities_attrs = {
activity_type: activity_type_for_task,
subject: title,
description: description,
happened_at: Time.current,
user: user,
organization: organization,
contact: contact,
opportunity: opportunity,
created_by: user,
updated_by: user
}
Activity.create!(activities_attrs)
end
def activity_type_for_task
{
"follow_up" => "follow_up",
"call" => "call",
"email" => "email_sent",
"meeting" => "meeting",
"demo" => "demo",
"proposal" => "proposal_sent",
"generic" => "other"
}.fetch(task_type, "other")
end
end