Include autenticazione, progetti isolati, mail marketing HTML con SMTP, test A/B e editor WYSIWYG. Co-authored-by: Cursor <cursoragent@cursor.com>
117 lines
3.9 KiB
Ruby
117 lines
3.9 KiB
Ruby
class Organization < ApplicationRecord
|
|
include Auditable
|
|
|
|
belongs_to :assigned_user, class_name: "User", optional: true
|
|
|
|
has_many :organization_projects, dependent: :destroy
|
|
has_many :projects, through: :organization_projects
|
|
has_many :contacts, dependent: :destroy
|
|
has_many :opportunities, dependent: :destroy
|
|
has_many :activities, dependent: :destroy
|
|
has_many :tasks, dependent: :destroy
|
|
has_many :mailing_recipients, dependent: :destroy
|
|
|
|
has_one :primary_contact, -> { where(primary_contact: true) }, class_name: "Contact", inverse_of: :organization
|
|
|
|
validates :name, presence: true
|
|
validates :status, inclusion: { in: Catalog::ORGANIZATION_STATUSES.keys }
|
|
validates :organization_type, inclusion: { in: Catalog::ORGANIZATION_TYPES.keys }
|
|
validates :lead_source, inclusion: { in: Catalog::LEAD_SOURCES.keys }, allow_blank: true
|
|
validates :team_gender, inclusion: { in: Catalog::TEAM_GENDERS.keys }, allow_blank: true
|
|
validates :streaming_status, inclusion: { in: Catalog::STREAMING_STATUSES.keys }, allow_blank: true
|
|
validates :email, format: { with: URI::MailTo::EMAIL_REGEXP }, allow_blank: true
|
|
validate :must_have_at_least_one_project
|
|
before_validation :assign_current_project_if_needed, on: :create
|
|
|
|
scope :prospects, -> { where(status: "prospect") }
|
|
scope :customers, -> { where(status: %w[active_customer inactive_customer]) }
|
|
scope :active_customers, -> { where(status: "active_customer") }
|
|
scope :for_project, ->(project) {
|
|
return none if project.nil?
|
|
|
|
joins(:organization_projects).where(organization_projects: { project_id: project.id }).distinct
|
|
}
|
|
scope :search, ->(query) {
|
|
return all if query.blank?
|
|
|
|
q = "%#{sanitize_sql_like(query.strip)}%"
|
|
left_joins(:contacts).where(
|
|
"organizations.name ILIKE :q OR organizations.city ILIKE :q OR organizations.email ILIKE :q OR organizations.phone ILIKE :q OR organizations.website ILIKE :q OR contacts.first_name ILIKE :q OR contacts.last_name ILIKE :q OR contacts.email ILIKE :q OR contacts.phone ILIKE :q OR contacts.mobile ILIKE :q",
|
|
q: q
|
|
).distinct
|
|
}
|
|
|
|
def status_label
|
|
Catalog.label_for(Catalog::ORGANIZATION_STATUSES, status)
|
|
end
|
|
|
|
def organization_type_label
|
|
Catalog.label_for(Catalog::ORGANIZATION_TYPES, organization_type)
|
|
end
|
|
|
|
def lead_source_label
|
|
Catalog.label_for(Catalog::LEAD_SOURCES, lead_source)
|
|
end
|
|
|
|
def team_gender_label
|
|
Catalog.label_for(Catalog::TEAM_GENDERS, team_gender)
|
|
end
|
|
|
|
def streaming_status_label
|
|
Catalog.label_for(Catalog::STREAMING_STATUSES, streaming_status)
|
|
end
|
|
|
|
def campaign_opportunity(project = nil)
|
|
list = opportunities.to_a
|
|
list = list.select { |opp| opp.project_id == project.id } if project
|
|
list.max_by(&:updated_at)
|
|
end
|
|
|
|
def primary_pipeline_stage(project = nil)
|
|
scope = opportunities
|
|
scope = scope.where(project_id: project.id) if project
|
|
scope.open_stage.order(updated_at: :desc).first&.pipeline_stage ||
|
|
scope.order(updated_at: :desc).first&.pipeline_stage
|
|
end
|
|
|
|
def next_pending_task
|
|
tasks.pending.order(:due_at).first
|
|
end
|
|
|
|
def last_activity_at
|
|
activities.maximum(:happened_at)
|
|
end
|
|
|
|
def days_since_last_activity
|
|
return nil unless last_activity_at
|
|
|
|
((Time.current - last_activity_at) / 1.day).floor
|
|
end
|
|
|
|
def mark_as_active_customer!
|
|
update!(status: "active_customer") if status != "active_customer"
|
|
end
|
|
|
|
def ensure_in_project!(project)
|
|
return if project.nil?
|
|
return if projects.exists?(project.id)
|
|
|
|
projects << project
|
|
end
|
|
|
|
private
|
|
|
|
def assign_current_project_if_needed
|
|
return if organization_projects.any? || project_ids.reject(&:blank?).any?
|
|
return unless Current.project
|
|
|
|
organization_projects.build(project: Current.project)
|
|
end
|
|
|
|
def must_have_at_least_one_project
|
|
return if organization_projects.any? || project_ids.reject(&:blank?).any?
|
|
|
|
errors.add(:projects, "seleziona almeno un progetto")
|
|
end
|
|
end
|