feat: ticket enhancemnet
This commit is contained in:
@@ -4,8 +4,10 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"be.ems/lib/config"
|
||||
"be.ems/lib/dborm"
|
||||
"be.ems/lib/email"
|
||||
"be.ems/lib/log"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
@@ -97,7 +99,7 @@ func (s *CallbackTicketService) SelectCallbackTicketByPage(pageNum int, pageSize
|
||||
return tickets, int(total), nil
|
||||
}
|
||||
|
||||
func (s *CallbackTicketService) InsertCallbackTicket(ticket CallbackTicket) error {
|
||||
func (s *CallbackTicketService) InsertCallbackTicket(ticket *CallbackTicket) error {
|
||||
// 判断主叫号码是否已存在未处理完的工单
|
||||
var existingCount int64
|
||||
if err := s.getDB().Table("mf_callback_ticket").
|
||||
@@ -110,7 +112,7 @@ func (s *CallbackTicketService) InsertCallbackTicket(ticket CallbackTicket) erro
|
||||
return fmt.Errorf("caller %s already has a pending ticket", ticket.CallerNumber)
|
||||
}
|
||||
// 这里可以使用ORM或其他方式将ticket插入到数据库中
|
||||
if err := s.getDB().Table("mf_callback_ticket").Create(&ticket).Error; err != nil {
|
||||
if err := s.getDB().Table("mf_callback_ticket").Create(ticket).Error; err != nil {
|
||||
return fmt.Errorf("failed to insert callback ticket: %w", err)
|
||||
}
|
||||
return nil
|
||||
@@ -174,7 +176,7 @@ func (s *CallbackTicketService) GetLastAssignedAgent() (string, error) {
|
||||
var lastTicket CallbackTicket
|
||||
if err := s.getDB().Table("mf_callback_ticket").
|
||||
Where("agent_name <> ''").
|
||||
Order("created_at DESC").
|
||||
Order("created_at DESC, ticket_id DESC").
|
||||
First(&lastTicket).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
// 没有记录属于正常情况,返回空字符串
|
||||
@@ -377,14 +379,137 @@ func (s *CallbackTicketService) UpdateTicketToTimeout(ticket *CallbackTicket, or
|
||||
|
||||
// 新工单分配后发送邮件通知
|
||||
if newAgent.Email != "" {
|
||||
subject := "新工单自动重建通知"
|
||||
body := fmt.Sprintf("您被分配了一个自动重建的回拨工单,主叫号码:%s", newTicket.CallerNumber)
|
||||
go email.SendEmail(newAgent.Email, subject, body)
|
||||
// 发送邮件通知
|
||||
// 获取SMTP配置
|
||||
emailConfig := config.GetSMTPConfig()
|
||||
if emailConfig != nil && emailConfig.Enabled {
|
||||
// 创建配置副本,避免修改全局配置
|
||||
emailCopy := *emailConfig // 浅拷贝结构体
|
||||
|
||||
// 合并配置中的To地址和当前工单的座席邮箱
|
||||
var recipients []string
|
||||
|
||||
// 添加配置中的原始收件人(如管理员、监控人员等)
|
||||
if len(emailConfig.To) > 0 {
|
||||
recipients = append(recipients, emailConfig.To...)
|
||||
}
|
||||
|
||||
// 添加当前工单的座席邮箱
|
||||
recipients = append(recipients, ticket.AgentEmail)
|
||||
|
||||
// 去重处理(避免重复邮箱)
|
||||
emailCopy.To = email.RemoveDuplicateEmails(recipients)
|
||||
|
||||
// 设置邮件主题和内容
|
||||
emailCopy.Subject = "新工单自动重建通知"
|
||||
emailCopy.Body = fmt.Sprintf("您被分配了一个自动重建的回拨工单,ID: %d, 主叫号码:%s, 请及时处理。",
|
||||
newTicket.TicketId, newTicket.CallerNumber)
|
||||
go email.SendEmailWithGomail(emailCopy)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// BatchUpdateTimeoutTickets 批量处理超时工单
|
||||
func (s *CallbackTicketService) BatchUpdateTimeoutTickets(tickets []CallbackTicket, originalStatus string, agents []AgentInfo) error {
|
||||
if len(tickets) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获取当前最后分配的座席
|
||||
lastAssignedAgent, err := s.GetLastAssignedAgent()
|
||||
if err != nil {
|
||||
log.Errorf("获取最后分配座席失败: %v", err)
|
||||
lastAssignedAgent = ""
|
||||
}
|
||||
|
||||
now := time.Now().UnixMicro()
|
||||
var successCount int
|
||||
for i, ticket := range tickets {
|
||||
// 1. 更新原工单为超时
|
||||
updatedTicket := CallbackTicket{
|
||||
TicketId: ticket.TicketId,
|
||||
Status: TicketStatusTimeout.Enum(),
|
||||
Comment: fmt.Sprintf("%s - 工单状态为 %s 处理超时,系统自动更新为超时状态", ticket.Comment, originalStatus),
|
||||
UpdatedAt: &now,
|
||||
}
|
||||
if err := s.getDB().Table("mf_callback_ticket").
|
||||
Where("ticket_id = ?", ticket.TicketId).
|
||||
Updates(updatedTicket).Error; err != nil {
|
||||
log.Errorf("更新工单 %d 状态失败: %v", ticket.TicketId, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// 2. 选择下一个座席(使用批处理中维护的lastAssignedAgent)
|
||||
newAgent := s.SelectNextAgent(agents, lastAssignedAgent)
|
||||
if newAgent == nil {
|
||||
log.Errorf("没有可用的座席分配给工单 %d", ticket.TicketId)
|
||||
continue
|
||||
}
|
||||
|
||||
// 3. 创建新工单
|
||||
newTicket := CallbackTicket{
|
||||
CallerNumber: ticket.CallerNumber,
|
||||
CalleeNumber: ticket.CalleeNumber,
|
||||
Status: TicketStatusNew.Enum(),
|
||||
AgentName: newAgent.Name,
|
||||
AgentEmail: newAgent.Email,
|
||||
AgentMobile: newAgent.Mobile,
|
||||
Comment: fmt.Sprintf("由超时工单 %d 自动重建", ticket.TicketId),
|
||||
MsdData: ticket.MsdData,
|
||||
RmUid: ticket.RmUid,
|
||||
CreatedAt: now + int64(i), // 确保每个工单的创建时间不同,
|
||||
UpdatedAt: nil,
|
||||
}
|
||||
if err := s.getDB().Table("mf_callback_ticket").Create(&newTicket).Error; err != nil {
|
||||
log.Errorf("创建新工单失败: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// 4. 更新最后分配的座席
|
||||
lastAssignedAgent = newAgent.Name
|
||||
|
||||
// 5. 发送邮件通知
|
||||
if newAgent.Email != "" {
|
||||
// 发送邮件通知
|
||||
// 获取SMTP配置
|
||||
emailConfig := config.GetSMTPConfig()
|
||||
if emailConfig != nil && emailConfig.Enabled {
|
||||
// 创建配置副本,避免修改全局配置
|
||||
emailCopy := *emailConfig // 浅拷贝结构体
|
||||
|
||||
// 合并配置中的To地址和当前工单的座席邮箱
|
||||
var recipients []string
|
||||
|
||||
// 添加配置中的原始收件人(如管理员、监控人员等)
|
||||
if len(emailConfig.To) > 0 {
|
||||
recipients = append(recipients, emailConfig.To...)
|
||||
}
|
||||
|
||||
// 添加当前工单的座席邮箱
|
||||
recipients = append(recipients, ticket.AgentEmail)
|
||||
|
||||
// 去重处理(避免重复邮箱)
|
||||
emailCopy.To = email.RemoveDuplicateEmails(recipients)
|
||||
|
||||
// 设置邮件主题和内容
|
||||
emailCopy.Subject = "新工单自动重建通知"
|
||||
emailCopy.Body = fmt.Sprintf("您被分配了一个自动重建的回拨工单,ID: %d, 主叫号码:%s, 请及时处理。",
|
||||
newTicket.TicketId, newTicket.CallerNumber)
|
||||
go email.SendEmailWithGomail(emailCopy)
|
||||
}
|
||||
}
|
||||
|
||||
successCount++
|
||||
log.Infof("工单 %d 已重建为新工单 %d,分配给座席 %s (第%d个处理)",
|
||||
ticket.TicketId, newTicket.TicketId, newAgent.Name, i+1)
|
||||
}
|
||||
|
||||
log.Infof("批量处理完成,成功处理 %d/%d 个超时工单", successCount, len(tickets))
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindNearlyTimeoutTickets 查询即将超时的工单
|
||||
func (s *CallbackTicketService) FindNearlyTimeoutTickets(status string, timeoutMicros int64, aheadMicros int64) ([]CallbackTicket, error) {
|
||||
nowMicros := time.Now().UnixMicro()
|
||||
|
||||
Reference in New Issue
Block a user