feat: harden support, localize knowledge and add operator availability [skip ci]
Source-only publication of reviewed commit 64e96a7f423673dc29ad56485be9fc79bce8af1c.
Passed in isolation: focused frontend/backend tests, race checks, TypeScript typecheck, lint, Go compilation, Flowgram build, and deterministic SDK build/tests.
Not accepted as a production release: Next.js export/native assembly remains blocked by environment memory limits; browser interaction and MySQL staging acceptance remain unverified. No production server, database/schema, runtime configuration, deployment, release tag, or workflow execution was performed.
Expected source tree: 0a4a7528e9.
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
// Modified in AgentDeskNext: authenticated support availability and calendars.
|
||||
package services
|
||||
|
||||
import (
|
||||
@@ -8,6 +9,7 @@ import (
|
||||
"agent-desk/internal/pkg/errorsx"
|
||||
"agent-desk/internal/pkg/utils"
|
||||
"agent-desk/internal/repositories"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -79,11 +81,18 @@ func (s *agentProfileService) GetUserIDsByTeamID(teamID int64) []int64 {
|
||||
|
||||
// GetDispatchAgents 获取可用于分配会话的客服
|
||||
func (s *agentProfileService) GetDispatchAgents(teamIds []int64) []models.AgentProfile {
|
||||
return AgentProfileService.Find(sqls.NewCnd().
|
||||
In("team_id", teamIds).
|
||||
Eq("status", enums.StatusOk).
|
||||
Eq("auto_assign_enabled", true).
|
||||
Eq("service_status", enums.ServiceStatusIdle))
|
||||
profiles, err := repositories.SupportAvailabilityRepository.Profiles(sqls.DB(), teamIds)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
result := make([]models.AgentProfile, 0, len(profiles))
|
||||
for _, profile := range profiles {
|
||||
eligibility, err := SupportAvailabilityService.Evaluate(sqls.DB(), profile, true, time.Now(), 0)
|
||||
if err == nil && eligibility.Eligible {
|
||||
result = append(result, profile)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *agentProfileService) CreateAgentProfile(req request.CreateAgentProfileRequest, operator *dto.AuthPrincipal) (*models.AgentProfile, error) {
|
||||
@@ -115,12 +124,12 @@ func (s *agentProfileService) UpdateAgentProfile(req request.UpdateAgentProfileR
|
||||
return err
|
||||
}
|
||||
if err := repositories.AgentProfileRepository.Updates(sqls.DB(), req.ID, map[string]any{
|
||||
"user_id": item.UserID,
|
||||
"team_id": item.TeamID,
|
||||
"agent_code": item.AgentCode,
|
||||
"display_name": item.DisplayName,
|
||||
"avatar": item.Avatar,
|
||||
"service_status": item.ServiceStatus,
|
||||
"user_id": item.UserID,
|
||||
"team_id": item.TeamID,
|
||||
"agent_code": item.AgentCode,
|
||||
"display_name": item.DisplayName,
|
||||
"avatar": item.Avatar,
|
||||
// Availability is managed only through the dedicated guarded endpoint.
|
||||
"max_concurrent_count": item.MaxConcurrentCount,
|
||||
"priority_level": item.PriorityLevel,
|
||||
"auto_assign_enabled": item.AutoAssignEnabled,
|
||||
@@ -169,7 +178,7 @@ func (s *agentProfileService) buildProfileModel(id int64, req request.CreateAgen
|
||||
if exists := s.Take("agent_code = ? AND id <> ?", req.AgentCode, id); exists != nil {
|
||||
return nil, errorsx.InvalidParamI18n("error.e0163")
|
||||
}
|
||||
if !enums.IsValidServiceStatus(req.ServiceStatus) {
|
||||
if !enums.IsValidServiceStatus(req.ServiceStatus) || (id == 0 && req.ServiceStatus == enums.ServiceStatusVacation) {
|
||||
return nil, errorsx.InvalidParamI18n("error.e0165")
|
||||
}
|
||||
if req.MaxConcurrentCount < 0 {
|
||||
@@ -197,11 +206,23 @@ func (s *agentProfileService) dispatchPendingConversationsIfEligible(item *model
|
||||
if item.Status != enums.StatusOk {
|
||||
return
|
||||
}
|
||||
if !item.AutoAssignEnabled || item.MaxConcurrentCount <= 0 {
|
||||
if !item.AutoAssignEnabled {
|
||||
return
|
||||
}
|
||||
if item.ServiceStatus != enums.ServiceStatusIdle {
|
||||
if effectiveSupportStatus(*item, time.Now()) != enums.ServiceStatusIdle {
|
||||
return
|
||||
}
|
||||
_, _ = ConversationDispatchService.DispatchPendingConversations(0)
|
||||
}
|
||||
|
||||
func (s *agentProfileService) FilterEffectiveServiceStatus(cnd *sqls.Cnd, value string) error {
|
||||
if strings.TrimSpace(value) == "" {
|
||||
return nil
|
||||
}
|
||||
number, err := strconv.Atoi(value)
|
||||
if err != nil || !enums.IsValidServiceStatus(enums.ServiceStatus(number)) {
|
||||
return errorsx.InvalidParamI18n("error.supportAvailability.invalidStatus")
|
||||
}
|
||||
repositories.SupportAvailabilityRepository.EffectiveStatusCondition(cnd, enums.ServiceStatus(number), time.Now())
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user