Files
assistant-storefront/enterprise/app/services/sla/evaluate_applied_sla_service.rb
Liang XJ 092fb2e083
Some checks failed
Lock Threads / action (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
Publish Chatwoot EE docker images / build (linux/amd64, ubuntu-latest) (push) Has been cancelled
Publish Chatwoot EE docker images / build (linux/arm64, ubuntu-22.04-arm) (push) Has been cancelled
Publish Chatwoot EE docker images / merge (push) Has been cancelled
Publish Chatwoot CE docker images / build (linux/amd64, ubuntu-latest) (push) Has been cancelled
Publish Chatwoot CE docker images / build (linux/arm64, ubuntu-22.04-arm) (push) Has been cancelled
Publish Chatwoot CE docker images / merge (push) Has been cancelled
Run Chatwoot CE spec / lint-backend (push) Has been cancelled
Run Chatwoot CE spec / lint-frontend (push) Has been cancelled
Run Chatwoot CE spec / frontend-tests (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (0, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (1, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (10, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (11, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (12, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (13, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (14, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (15, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (2, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (3, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (4, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (5, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (6, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (7, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (8, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (9, 16) (push) Has been cancelled
Run Linux nightly installer / nightly (push) Has been cancelled
Initial commit: Add logistics and order_detail message types
- Add Logistics component with progress tracking
- Add OrderDetail component for order information
- Support data-driven steps and actions
- Add blue color scale to widget SCSS
- Fix node overflow and progress bar rendering issues
- Add English translations for dashboard components

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 11:16:56 +08:00

108 lines
3.9 KiB
Ruby

class Sla::EvaluateAppliedSlaService
pattr_initialize [:applied_sla!]
def perform
check_sla_thresholds
# We will calculate again in the next iteration
return unless applied_sla.conversation.resolved?
# after conversation is resolved, we will check if the SLA was hit or missed
handle_hit_sla(applied_sla)
end
private
def check_sla_thresholds
[:first_response_time_threshold, :next_response_time_threshold, :resolution_time_threshold].each do |threshold|
next if applied_sla.sla_policy.send(threshold).blank?
send("check_#{threshold}", applied_sla, applied_sla.conversation, applied_sla.sla_policy)
end
end
def still_within_threshold?(threshold)
Time.zone.now.to_i < threshold
end
def check_first_response_time_threshold(applied_sla, conversation, sla_policy)
threshold = conversation.created_at.to_i + sla_policy.first_response_time_threshold.to_i
return if first_reply_was_within_threshold?(conversation, threshold)
return if still_within_threshold?(threshold)
handle_missed_sla(applied_sla, 'frt')
end
def first_reply_was_within_threshold?(conversation, threshold)
conversation.first_reply_created_at.present? && conversation.first_reply_created_at.to_i <= threshold
end
def check_next_response_time_threshold(applied_sla, conversation, sla_policy)
# still waiting for first reply, so covered under first response time threshold
return if conversation.first_reply_created_at.blank?
# Waiting on customer response, no need to check next response time threshold
return if conversation.waiting_since.blank?
threshold = conversation.waiting_since.to_i + sla_policy.next_response_time_threshold.to_i
return if still_within_threshold?(threshold)
handle_missed_sla(applied_sla, 'nrt')
end
def get_last_message_id(conversation)
# TODO: refactor the method to fetch last message without reply
conversation.messages.where(message_type: :incoming).last&.id
end
def already_missed?(applied_sla, type, meta = {})
SlaEvent.exists?(applied_sla: applied_sla, event_type: type, meta: meta)
end
def check_resolution_time_threshold(applied_sla, conversation, sla_policy)
return if conversation.resolved?
threshold = conversation.created_at.to_i + sla_policy.resolution_time_threshold.to_i
return if still_within_threshold?(threshold)
handle_missed_sla(applied_sla, 'rt')
end
def handle_missed_sla(applied_sla, type, meta = {})
meta = { message_id: get_last_message_id(applied_sla.conversation) } if type == 'nrt'
return if already_missed?(applied_sla, type, meta)
create_sla_event(applied_sla, type, meta)
Rails.logger.warn "SLA #{type} missed for conversation #{applied_sla.conversation.id} " \
"in account #{applied_sla.account_id} " \
"for sla_policy #{applied_sla.sla_policy.id}"
applied_sla.update!(sla_status: 'active_with_misses') if applied_sla.sla_status != 'active_with_misses'
end
def handle_hit_sla(applied_sla)
if applied_sla.active?
applied_sla.update!(sla_status: 'hit')
Rails.logger.info "SLA hit for conversation #{applied_sla.conversation.id} " \
"in account #{applied_sla.account_id} " \
"for sla_policy #{applied_sla.sla_policy.id}"
else
applied_sla.update!(sla_status: 'missed')
Rails.logger.info "SLA missed for conversation #{applied_sla.conversation.id} " \
"in account #{applied_sla.account_id} " \
"for sla_policy #{applied_sla.sla_policy.id}"
end
end
def create_sla_event(applied_sla, event_type, meta = {})
SlaEvent.create!(
applied_sla: applied_sla,
conversation: applied_sla.conversation,
event_type: event_type,
meta: meta,
account: applied_sla.account,
inbox: applied_sla.conversation.inbox,
sla_policy: applied_sla.sla_policy
)
end
end