package service import ( "context" "fmt" "github.com/gochat/gochat/internal/model" "github.com/gochat/gochat/internal/repository" applogger "github.com/gochat/gochat/pkg/logger" ) // SlaEventService 创建和管理SLA事件记录。 // Reference: Chatwoot app/models/sla_event.rb // 事件类型: frt/nrt/rt missed, 以及hit事件(会话resolved时) type SlaEventService struct { slaEventRepo *repository.SlaEventRepo conversationRepo *repository.ConversationRepo } // NewSlaEventService 创建新的SLA事件服务。 func NewSlaEventService( slaEventRepo *repository.SlaEventRepo, conversationRepo *repository.ConversationRepo, ) *SlaEventService { return &SlaEventService{ slaEventRepo: slaEventRepo, conversationRepo: conversationRepo, } } // NewSlaEventServiceSimple 创建不需要conversationRepo的简化版本(用于内部调用)。 // 内部调用时InboxID从其他地方获取。 func NewSlaEventServiceSimple(slaEventRepo *repository.SlaEventRepo) *SlaEventService { return &SlaEventService{ slaEventRepo: slaEventRepo, } } // CreateMissedEvent 创建一个SLA阈值missed事件记录。 // Reference: Chatwoot — 当SLA阈值未被满足时,创建missed事件 // eventType: frt/nrt/rt,标识哪个阈值被违反 func (s *SlaEventService) CreateMissedEvent( ctx context.Context, appliedSla *model.AppliedSLA, eventType model.SLAEventType, ) error { // 获取InboxID: 从会话获取 inboxID := uint(0) if s.conversationRepo != nil { conversation, err := s.conversationRepo.FindByID(ctx, appliedSla.ConversationID) if err == nil { inboxID = conversation.InboxID } else { applogger.L().Errorf("查找Conversation获取InboxID失败: %v", err) } } event := &model.SlaEvent{ AppliedSlaID: appliedSla.ID, AccountID: appliedSla.AccountID, ConversationID: appliedSla.ConversationID, InboxID: inboxID, SlaPolicyID: appliedSla.SlaPolicyID, EventType: eventType, } if err := s.slaEventRepo.Create(ctx, event); err != nil { return fmt.Errorf("创建SlaEvent missed记录失败: %w", err) } applogger.L().Infof("创建SlaEvent missed: AppliedSLA[%d] eventType=%s", appliedSla.ID, eventType) return nil } // CreateHitEvent 当会话resolved且所有阈值达标时,创建hit事件记录。 // Reference: Chatwoot — 当会话解决且SLA目标全部达标时,创建hit事件 func (s *SlaEventService) CreateHitEvent( ctx context.Context, appliedSla *model.AppliedSLA, ) error { // 获取InboxID: 从会话获取 inboxID := uint(0) if s.conversationRepo != nil { conversation, err := s.conversationRepo.FindByID(ctx, appliedSla.ConversationID) if err == nil { inboxID = conversation.InboxID } else { applogger.L().Errorf("查找Conversation获取InboxID失败: %v", err) } } event := &model.SlaEvent{ AppliedSlaID: appliedSla.ID, AccountID: appliedSla.AccountID, ConversationID: appliedSla.ConversationID, InboxID: inboxID, SlaPolicyID: appliedSla.SlaPolicyID, EventType: model.SLAEventFRT, // hit事件使用FRT作为标记类型 } if err := s.slaEventRepo.Create(ctx, event); err != nil { return fmt.Errorf("创建SlaEvent hit记录失败: %w", err) } applogger.L().Infof("创建SlaEvent hit: AppliedSLA[%d]", appliedSla.ID) return nil }