562 lines
18 KiB
Go
562 lines
18 KiB
Go
package services
|
|
|
|
import (
|
|
"agent-desk/internal/models"
|
|
"agent-desk/internal/pkg/dto"
|
|
"agent-desk/internal/pkg/dto/request"
|
|
"agent-desk/internal/pkg/enums"
|
|
"agent-desk/internal/pkg/errorsx"
|
|
"agent-desk/internal/pkg/i18nx"
|
|
"agent-desk/internal/pkg/utils"
|
|
"agent-desk/internal/repositories"
|
|
"slices"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"agent-desk/internal/pkg/httpx/params"
|
|
|
|
"github.com/mlogclub/simple/sqls"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
var AgentTeamScheduleService = newAgentTeamScheduleService()
|
|
|
|
func newAgentTeamScheduleService() *agentTeamScheduleService {
|
|
return &agentTeamScheduleService{}
|
|
}
|
|
|
|
type agentTeamScheduleService struct {
|
|
writeMu sync.Mutex
|
|
}
|
|
|
|
const maxAgentTeamScheduleBatchItems = 500
|
|
|
|
type AgentTeamScheduleBatchPreviewResult struct {
|
|
Total int
|
|
Conflict bool
|
|
Items []AgentTeamScheduleBatchPreviewItem
|
|
}
|
|
|
|
type AgentTeamScheduleBatchPreviewItem struct {
|
|
TeamID int64
|
|
TeamName string
|
|
Date time.Time
|
|
Weekday int
|
|
StartAt time.Time
|
|
EndAt time.Time
|
|
Remark string
|
|
Conflict bool
|
|
ConflictReason string
|
|
}
|
|
|
|
type AgentTeamScheduleBatchGenerateResult struct {
|
|
Created int
|
|
}
|
|
|
|
type batchScheduleCandidate struct {
|
|
TeamID int64
|
|
TeamName string
|
|
Date time.Time
|
|
StartAt time.Time
|
|
EndAt time.Time
|
|
Remark string
|
|
}
|
|
|
|
func (s *agentTeamScheduleService) Get(id int64) *models.AgentTeamSchedule {
|
|
return repositories.AgentTeamScheduleRepository.Get(sqls.DB(), id)
|
|
}
|
|
|
|
func (s *agentTeamScheduleService) Take(where ...interface{}) *models.AgentTeamSchedule {
|
|
return repositories.AgentTeamScheduleRepository.Take(sqls.DB(), where...)
|
|
}
|
|
|
|
func (s *agentTeamScheduleService) Find(cnd *sqls.Cnd) []models.AgentTeamSchedule {
|
|
return repositories.AgentTeamScheduleRepository.Find(sqls.DB(), cnd)
|
|
}
|
|
|
|
func (s *agentTeamScheduleService) FindOne(cnd *sqls.Cnd) *models.AgentTeamSchedule {
|
|
return repositories.AgentTeamScheduleRepository.FindOne(sqls.DB(), cnd)
|
|
}
|
|
|
|
func (s *agentTeamScheduleService) FindPageByParams(params *params.QueryParams) (list []models.AgentTeamSchedule, paging *sqls.Paging) {
|
|
return repositories.AgentTeamScheduleRepository.FindPageByParams(sqls.DB(), params)
|
|
}
|
|
|
|
func (s *agentTeamScheduleService) FindPageByCnd(cnd *sqls.Cnd) (list []models.AgentTeamSchedule, paging *sqls.Paging) {
|
|
return repositories.AgentTeamScheduleRepository.FindPageByCnd(sqls.DB(), cnd)
|
|
}
|
|
|
|
func (s *agentTeamScheduleService) Count(cnd *sqls.Cnd) int64 {
|
|
return repositories.AgentTeamScheduleRepository.Count(sqls.DB(), cnd)
|
|
}
|
|
|
|
func (s *agentTeamScheduleService) FindCalendarSchedules(req request.AgentTeamScheduleCalendarRequest) ([]models.AgentTeamSchedule, error) {
|
|
startAtValue, err := parseRequiredDateTime(req.StartAt, "error.agentTeamSchedule.startAtInvalid", "error.agentTeamSchedule.startAtInvalidWithFormat")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
endAtValue, err := parseRequiredDateTime(req.EndAt, "error.agentTeamSchedule.endAtInvalid", "error.agentTeamSchedule.endAtInvalidWithFormat")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !endAtValue.After(startAtValue) {
|
|
return nil, errorsx.InvalidParamI18n("error.e0296")
|
|
}
|
|
return repositories.AgentTeamScheduleRepository.FindByTimeRange(sqls.DB(), startAtValue, endAtValue, req.TeamID), nil
|
|
}
|
|
|
|
func (s *agentTeamScheduleService) Create(t *models.AgentTeamSchedule) error {
|
|
return repositories.AgentTeamScheduleRepository.Create(sqls.DB(), t)
|
|
}
|
|
|
|
func (s *agentTeamScheduleService) Update(t *models.AgentTeamSchedule) error {
|
|
return repositories.AgentTeamScheduleRepository.Update(sqls.DB(), t)
|
|
}
|
|
|
|
func (s *agentTeamScheduleService) Updates(id int64, columns map[string]interface{}) error {
|
|
return repositories.AgentTeamScheduleRepository.Updates(sqls.DB(), id, columns)
|
|
}
|
|
|
|
func (s *agentTeamScheduleService) UpdateColumn(id int64, name string, value interface{}) error {
|
|
return repositories.AgentTeamScheduleRepository.UpdateColumn(sqls.DB(), id, name, value)
|
|
}
|
|
|
|
func (s *agentTeamScheduleService) Delete(id int64) {
|
|
repositories.AgentTeamScheduleRepository.Delete(sqls.DB(), id)
|
|
}
|
|
|
|
func (s *agentTeamScheduleService) CreateAgentTeamSchedule(req request.CreateAgentTeamScheduleRequest, operator *dto.AuthPrincipal) (*models.AgentTeamSchedule, error) {
|
|
if operator == nil {
|
|
return nil, errorsx.UnauthorizedI18n("error.auth.expired")
|
|
}
|
|
s.writeMu.Lock()
|
|
item, err := s.buildScheduleModel(0, req.TeamID, req.StartAt, req.EndAt, req.Remark)
|
|
if err != nil {
|
|
s.writeMu.Unlock()
|
|
return nil, err
|
|
}
|
|
item.AuditFields = utils.BuildAuditFields(operator)
|
|
if err := repositories.AgentTeamScheduleRepository.Create(sqls.DB(), item); err != nil {
|
|
s.writeMu.Unlock()
|
|
return nil, err
|
|
}
|
|
s.writeMu.Unlock()
|
|
s.dispatchPendingConversationsIfActive(item)
|
|
return item, nil
|
|
}
|
|
|
|
func (s *agentTeamScheduleService) UpdateAgentTeamSchedule(req request.UpdateAgentTeamScheduleRequest, operator *dto.AuthPrincipal) error {
|
|
if operator == nil {
|
|
return errorsx.UnauthorizedI18n("error.auth.expired")
|
|
}
|
|
s.writeMu.Lock()
|
|
if s.Get(req.ID) == nil {
|
|
s.writeMu.Unlock()
|
|
return errorsx.InvalidParamI18n("error.e0172")
|
|
}
|
|
item, err := s.buildScheduleModel(req.ID, req.TeamID, req.StartAt, req.EndAt, req.Remark)
|
|
if err != nil {
|
|
s.writeMu.Unlock()
|
|
return err
|
|
}
|
|
if err := repositories.AgentTeamScheduleRepository.Updates(sqls.DB(), req.ID, map[string]any{
|
|
"team_id": item.TeamID,
|
|
"start_at": item.StartAt,
|
|
"end_at": item.EndAt,
|
|
"remark": item.Remark,
|
|
"update_user_id": operator.UserID,
|
|
"update_user_name": operator.Username,
|
|
"updated_at": time.Now(),
|
|
}); err != nil {
|
|
s.writeMu.Unlock()
|
|
return err
|
|
}
|
|
s.writeMu.Unlock()
|
|
s.dispatchPendingConversationsIfActive(item)
|
|
return nil
|
|
}
|
|
|
|
func (s *agentTeamScheduleService) DeleteAgentTeamSchedule(id int64) error {
|
|
if s.Get(id) == nil {
|
|
return errorsx.InvalidParamI18n("error.e0172")
|
|
}
|
|
repositories.AgentTeamScheduleRepository.Delete(sqls.DB(), id)
|
|
return nil
|
|
}
|
|
|
|
func (s *agentTeamScheduleService) BatchPreview(req request.AgentTeamScheduleBatchRequest, operator *dto.AuthPrincipal) (*AgentTeamScheduleBatchPreviewResult, error) {
|
|
if operator == nil {
|
|
return nil, errorsx.UnauthorizedI18n("error.auth.expired")
|
|
}
|
|
candidates, err := s.buildBatchScheduleCandidates(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
conflicts := s.findBatchConflict(candidates, req.Locale)
|
|
return buildBatchPreviewResult(candidates, conflicts), nil
|
|
}
|
|
|
|
func (s *agentTeamScheduleService) BatchGenerate(req request.AgentTeamScheduleBatchRequest, operator *dto.AuthPrincipal) (*AgentTeamScheduleBatchGenerateResult, error) {
|
|
if operator == nil {
|
|
return nil, errorsx.UnauthorizedI18n("error.auth.expired")
|
|
}
|
|
s.writeMu.Lock()
|
|
candidates, err := s.buildBatchScheduleCandidates(req)
|
|
if err != nil {
|
|
s.writeMu.Unlock()
|
|
return nil, err
|
|
}
|
|
conflicts := s.findBatchConflict(candidates, req.Locale)
|
|
for _, conflict := range conflicts {
|
|
if conflict != "" {
|
|
s.writeMu.Unlock()
|
|
return nil, errorsx.InvalidParamI18n("error.e0151")
|
|
}
|
|
}
|
|
|
|
schedules := make([]models.AgentTeamSchedule, 0, len(candidates))
|
|
for _, candidate := range candidates {
|
|
schedules = append(schedules, models.AgentTeamSchedule{
|
|
TeamID: candidate.TeamID,
|
|
StartAt: candidate.StartAt,
|
|
EndAt: candidate.EndAt,
|
|
Remark: candidate.Remark,
|
|
Status: enums.StatusOk,
|
|
AuditFields: utils.BuildAuditFields(operator),
|
|
})
|
|
}
|
|
if err := sqls.WithTransaction(func(ctx *sqls.TxContext) error {
|
|
conflicts := s.findBatchConflictByDB(ctx.Tx, candidates, req.Locale)
|
|
for _, conflict := range conflicts {
|
|
if conflict != "" {
|
|
return errorsx.InvalidParamI18n("error.e0151")
|
|
}
|
|
}
|
|
return repositories.AgentTeamScheduleRepository.CreateBatch(ctx.Tx, schedules)
|
|
}); err != nil {
|
|
s.writeMu.Unlock()
|
|
return nil, err
|
|
}
|
|
s.writeMu.Unlock()
|
|
for i := range schedules {
|
|
s.dispatchPendingConversationsIfActive(&schedules[i])
|
|
}
|
|
return &AgentTeamScheduleBatchGenerateResult{Created: len(schedules)}, nil
|
|
}
|
|
|
|
func (s *agentTeamScheduleService) buildScheduleModel(id, teamID int64, startAt, endAt, remark string) (*models.AgentTeamSchedule, error) {
|
|
if teamID <= 0 {
|
|
return nil, errorsx.InvalidParamI18n("error.e0326")
|
|
}
|
|
team := AgentTeamService.Get(teamID)
|
|
if team == nil {
|
|
return nil, errorsx.InvalidParamI18n("error.e0169")
|
|
}
|
|
if !slices.Contains(enums.StatusValues, team.Status) {
|
|
return nil, errorsx.InvalidParamI18n("error.e0174")
|
|
}
|
|
startAtValue, err := parseRequiredDateTime(startAt, "error.agentTeamSchedule.startAtInvalid", "error.agentTeamSchedule.startAtInvalidWithFormat")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
endAtValue, err := parseRequiredDateTime(endAt, "error.agentTeamSchedule.endAtInvalid", "error.agentTeamSchedule.endAtInvalidWithFormat")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !endAtValue.After(startAtValue) {
|
|
return nil, errorsx.InvalidParamI18n("error.e0296")
|
|
}
|
|
if !sameLocalDay(startAtValue, endAtValue) {
|
|
return nil, errorsx.InvalidParamI18n("error.e0132")
|
|
}
|
|
if startAtValue.Before(startOfLocalDay(time.Now())) {
|
|
return nil, errorsx.InvalidParamI18n("error.e0085")
|
|
}
|
|
overlapping := repositories.AgentTeamScheduleRepository.FindOverlappingByTeamIDsAndTimeRange(sqls.DB(), []int64{teamID}, startAtValue, endAtValue)
|
|
for _, item := range overlapping {
|
|
if item.ID != id {
|
|
return nil, errorsx.InvalidParamI18n("error.e0309")
|
|
}
|
|
}
|
|
return &models.AgentTeamSchedule{
|
|
TeamID: teamID,
|
|
StartAt: startAtValue,
|
|
EndAt: endAtValue,
|
|
Remark: strings.TrimSpace(remark),
|
|
}, nil
|
|
}
|
|
|
|
func (s *agentTeamScheduleService) buildBatchScheduleCandidates(req request.AgentTeamScheduleBatchRequest) ([]batchScheduleCandidate, error) {
|
|
teamIDs := uniquePositiveInt64s(req.TeamIDs)
|
|
if len(teamIDs) == 0 {
|
|
return nil, errorsx.InvalidParamI18n("error.e0326")
|
|
}
|
|
weekdays, err := normalizeBatchWeekdays(req.Weekdays)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
startDate, err := parseRequiredDate(req.StartDate, "error.agentTeamSchedule.startDateInvalid", "error.agentTeamSchedule.startDateInvalidWithFormat")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
endDate, err := parseRequiredDate(req.EndDate, "error.agentTeamSchedule.endDateInvalid", "error.agentTeamSchedule.endDateInvalidWithFormat")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if endDate.Before(startDate) {
|
|
return nil, errorsx.InvalidParamI18n("error.e0295")
|
|
}
|
|
if startDate.Before(startOfLocalDay(time.Now())) {
|
|
return nil, errorsx.InvalidParamI18n("error.e0085")
|
|
}
|
|
startClock, err := parseRequiredClock(req.StartTime, "error.agentTeamSchedule.startTimeInvalid", "error.agentTeamSchedule.startTimeInvalidWithFormat")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
endClock, err := parseRequiredClock(req.EndTime, "error.agentTeamSchedule.endTimeInvalid", "error.agentTeamSchedule.endTimeInvalidWithFormat")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
firstStartAt := combineDateAndClock(startDate, startClock)
|
|
firstEndAt := combineDateAndClock(startDate, endClock)
|
|
if !firstEndAt.After(firstStartAt) {
|
|
return nil, errorsx.InvalidParamI18n("error.e0296")
|
|
}
|
|
|
|
teams := AgentTeamService.FindByIds(teamIDs)
|
|
teamsByID := make(map[int64]models.AgentTeam, len(teams))
|
|
for _, team := range teams {
|
|
teamsByID[team.ID] = team
|
|
}
|
|
for _, teamID := range teamIDs {
|
|
team, ok := teamsByID[teamID]
|
|
if !ok || team.Status == enums.StatusDeleted {
|
|
return nil, errorsx.InvalidParamI18n("error.e0169")
|
|
}
|
|
if !slices.Contains(enums.StatusValues, team.Status) {
|
|
return nil, errorsx.InvalidParamI18n("error.e0174")
|
|
}
|
|
}
|
|
|
|
weekdaySet := make(map[int]struct{}, len(weekdays))
|
|
for _, weekday := range weekdays {
|
|
weekdaySet[weekday] = struct{}{}
|
|
}
|
|
candidates := make([]batchScheduleCandidate, 0)
|
|
remark := strings.TrimSpace(req.Remark)
|
|
for _, teamID := range teamIDs {
|
|
team := teamsByID[teamID]
|
|
for date := startDate; !date.After(endDate); date = date.AddDate(0, 0, 1) {
|
|
if _, ok := weekdaySet[weekdayForBatchRequest(date)]; !ok {
|
|
continue
|
|
}
|
|
if len(candidates) >= maxAgentTeamScheduleBatchItems {
|
|
return nil, errorsx.InvalidParamI18n("error.agentTeamSchedule.batchLimit", maxAgentTeamScheduleBatchItems)
|
|
}
|
|
candidates = append(candidates, batchScheduleCandidate{
|
|
TeamID: teamID,
|
|
TeamName: team.Name,
|
|
Date: date,
|
|
StartAt: combineDateAndClock(date, startClock),
|
|
EndAt: combineDateAndClock(date, endClock),
|
|
Remark: remark,
|
|
})
|
|
}
|
|
}
|
|
if len(candidates) == 0 {
|
|
return nil, errorsx.InvalidParamI18n("error.e0232")
|
|
}
|
|
return candidates, nil
|
|
}
|
|
|
|
func parseRequiredDate(value, emptyKey, formatKey string) (time.Time, error) {
|
|
value = strings.TrimSpace(value)
|
|
if value == "" {
|
|
return time.Time{}, errorsx.InvalidParamI18n(emptyKey)
|
|
}
|
|
ret, err := time.ParseInLocation(time.DateOnly, value, time.Local)
|
|
if err != nil {
|
|
return time.Time{}, errorsx.InvalidParamI18n(formatKey)
|
|
}
|
|
return startOfLocalDay(ret), nil
|
|
}
|
|
|
|
func parseRequiredClock(value, emptyKey, formatKey string) (time.Time, error) {
|
|
value = strings.TrimSpace(value)
|
|
if value == "" {
|
|
return time.Time{}, errorsx.InvalidParamI18n(emptyKey)
|
|
}
|
|
layouts := []string{"15:04", "15:04:05"}
|
|
for _, layout := range layouts {
|
|
if ret, err := time.ParseInLocation(layout, value, time.Local); err == nil {
|
|
return ret, nil
|
|
}
|
|
}
|
|
return time.Time{}, errorsx.InvalidParamI18n(formatKey)
|
|
}
|
|
|
|
func combineDateAndClock(date, clock time.Time) time.Time {
|
|
year, month, day := date.In(time.Local).Date()
|
|
hour, minute, second := clock.In(time.Local).Clock()
|
|
return time.Date(year, month, day, hour, minute, second, 0, time.Local)
|
|
}
|
|
|
|
func buildBatchPreviewResult(candidates []batchScheduleCandidate, conflicts map[int]string) *AgentTeamScheduleBatchPreviewResult {
|
|
items := make([]AgentTeamScheduleBatchPreviewItem, 0, len(candidates))
|
|
hasConflict := false
|
|
for i, candidate := range candidates {
|
|
conflictReason := conflicts[i]
|
|
conflict := conflictReason != ""
|
|
if conflict {
|
|
hasConflict = true
|
|
}
|
|
items = append(items, AgentTeamScheduleBatchPreviewItem{
|
|
TeamID: candidate.TeamID,
|
|
TeamName: candidate.TeamName,
|
|
Date: candidate.Date,
|
|
Weekday: weekdayForBatchRequest(candidate.Date),
|
|
StartAt: candidate.StartAt,
|
|
EndAt: candidate.EndAt,
|
|
Remark: candidate.Remark,
|
|
Conflict: conflict,
|
|
ConflictReason: conflictReason,
|
|
})
|
|
}
|
|
return &AgentTeamScheduleBatchPreviewResult{
|
|
Total: len(items),
|
|
Conflict: hasConflict,
|
|
Items: items,
|
|
}
|
|
}
|
|
|
|
func (s *agentTeamScheduleService) findBatchConflict(candidates []batchScheduleCandidate, locale string) map[int]string {
|
|
return s.findBatchConflictByDB(sqls.DB(), candidates, locale)
|
|
}
|
|
|
|
func (s *agentTeamScheduleService) findBatchConflictByDB(db *gorm.DB, candidates []batchScheduleCandidate, locale string) map[int]string {
|
|
conflicts := make(map[int]string)
|
|
if len(candidates) == 0 {
|
|
return conflicts
|
|
}
|
|
teamIDs := make([]int64, 0, len(candidates))
|
|
startAt := candidates[0].StartAt
|
|
endAt := candidates[0].EndAt
|
|
for _, candidate := range candidates {
|
|
teamIDs = append(teamIDs, candidate.TeamID)
|
|
if candidate.StartAt.Before(startAt) {
|
|
startAt = candidate.StartAt
|
|
}
|
|
if candidate.EndAt.After(endAt) {
|
|
endAt = candidate.EndAt
|
|
}
|
|
}
|
|
existing := repositories.AgentTeamScheduleRepository.FindOverlappingByTeamIDsAndTimeRange(db, uniquePositiveInt64s(teamIDs), startAt, endAt)
|
|
for i, candidate := range candidates {
|
|
for _, item := range existing {
|
|
if item.TeamID != candidate.TeamID {
|
|
continue
|
|
}
|
|
if item.StartAt.Before(candidate.EndAt) && item.EndAt.After(candidate.StartAt) {
|
|
conflicts[i] = i18nx.Getf(locale, "error.agentTeamSchedule.conflictRange", item.StartAt.Format(time.DateTime), item.EndAt.Format(time.DateTime))
|
|
break
|
|
}
|
|
}
|
|
}
|
|
return conflicts
|
|
}
|
|
|
|
func normalizeBatchWeekdays(values []int) ([]int, error) {
|
|
seen := make(map[int]struct{}, len(values))
|
|
ret := make([]int, 0, len(values))
|
|
for _, value := range values {
|
|
if value < 1 || value > 7 {
|
|
return nil, errorsx.InvalidParamI18n("error.e0228")
|
|
}
|
|
if _, ok := seen[value]; ok {
|
|
continue
|
|
}
|
|
seen[value] = struct{}{}
|
|
ret = append(ret, value)
|
|
}
|
|
if len(ret) == 0 {
|
|
return nil, errorsx.InvalidParamI18n("error.e0329")
|
|
}
|
|
return ret, nil
|
|
}
|
|
|
|
func weekdayForBatchRequest(value time.Time) int {
|
|
if value.Weekday() == time.Sunday {
|
|
return 7
|
|
}
|
|
return int(value.Weekday())
|
|
}
|
|
|
|
func uniquePositiveInt64s(values []int64) []int64 {
|
|
seen := make(map[int64]struct{}, len(values))
|
|
ret := make([]int64, 0, len(values))
|
|
for _, value := range values {
|
|
if value <= 0 {
|
|
continue
|
|
}
|
|
if _, ok := seen[value]; ok {
|
|
continue
|
|
}
|
|
seen[value] = struct{}{}
|
|
ret = append(ret, value)
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func parseRequiredDateTime(value, emptyKey, formatKey string) (time.Time, error) {
|
|
value = strings.TrimSpace(value)
|
|
if value == "" {
|
|
return time.Time{}, errorsx.InvalidParamI18n(emptyKey)
|
|
}
|
|
ret, err := parseDateTimeValue(value)
|
|
if err != nil {
|
|
return time.Time{}, errorsx.InvalidParamI18n(formatKey)
|
|
}
|
|
return ret, nil
|
|
}
|
|
|
|
func parseDateTimeValue(value string) (time.Time, error) {
|
|
layouts := []string{
|
|
time.DateTime,
|
|
time.RFC3339,
|
|
"2006-01-02T15:04",
|
|
"2006-01-02T15:04:05",
|
|
}
|
|
for _, layout := range layouts {
|
|
if ret, err := time.ParseInLocation(layout, value, time.Local); err == nil {
|
|
return ret, nil
|
|
}
|
|
}
|
|
return time.Time{}, errorsx.InvalidParamI18n("error.e0227")
|
|
}
|
|
|
|
func startOfLocalDay(value time.Time) time.Time {
|
|
year, month, day := value.In(time.Local).Date()
|
|
return time.Date(year, month, day, 0, 0, 0, 0, time.Local)
|
|
}
|
|
|
|
func sameLocalDay(a, b time.Time) bool {
|
|
aYear, aMonth, aDay := a.In(time.Local).Date()
|
|
bYear, bMonth, bDay := b.In(time.Local).Date()
|
|
return aYear == bYear && aMonth == bMonth && aDay == bDay
|
|
}
|
|
|
|
func (s *agentTeamScheduleService) dispatchPendingConversationsIfActive(item *models.AgentTeamSchedule) {
|
|
if item == nil {
|
|
return
|
|
}
|
|
if item.Status != enums.StatusOk {
|
|
return
|
|
}
|
|
now := time.Now()
|
|
if item.StartAt.After(now) || !item.EndAt.After(now) {
|
|
return
|
|
}
|
|
_, _ = ConversationDispatchService.DispatchPendingConversations(0)
|
|
}
|