package autoassignment // GORM models for the auto-assignment system. // // Reference: Chatwoot AutoAssignment pattern // - AssignmentPolicy: global policy for how conversations are assigned // (round_robin, longest_waiting). Has fair_distribution_limit and // fair_distribution_window for rate limiting per agent. // - InboxAssignmentPolicy: per-inbox override of the global policy. // Each inbox can have its own assignment policy and rate limits. // // Pattern: gochat models embed model.Base (ID, CreatedAt, UpdatedAt, DeletedAt), // use TableName() method, and use gorm struct tags. import ( "github.com/gochat/gochat/internal/model" ) // AssignmentPolicyType defines the type of auto-assignment policy. type AssignmentPolicyType string const ( // PolicyRoundRobin assigns conversations to agents in round-robin order. // Reference: Chatwoot InboxRoundRobinService PolicyRoundRobin AssignmentPolicyType = "round_robin" // PolicyLongestWaiting assigns conversations to the agent with the // longest idle time since their last assignment. // Reference: Chatwoot "longest_waiting" policy (planned feature) PolicyLongestWaiting AssignmentPolicyType = "longest_waiting" // PolicyLowestLoad assigns conversations to the agent with the // fewest currently open conversations. // Reference: Chatwoot "least_busy" concept — agent with lowest workload. PolicyLowestLoad AssignmentPolicyType = "lowest_load" ) // AssignmentPolicy represents the global auto-assignment policy for an account. // Reference: Chatwoot AssignmentPolicy model // - Defines how unassigned conversations are distributed among agents // - fair_distribution_limit: max assignments per agent per window (default 5) // - fair_distribution_window: time window in seconds for rate limiting (default 300 = 5 min) type AssignmentPolicy struct { model.Base AccountID uint `gorm:"index;not null" json:"account_id"` Policy AssignmentPolicyType `gorm:"size:50;default:round_robin" json:"policy"` FairDistributionLimit int `gorm:"default:5" json:"fair_distribution_limit"` FairDistributionWindow int `gorm:"default:300" json:"fair_distribution_window"` // seconds Active bool `gorm:"default:true" json:"active"` } func (AssignmentPolicy) TableName() string { return "assignment_policies" } // InboxAssignmentPolicy represents a per-inbox override of the global assignment policy. // Reference: Chatwoot InboxAssignmentPolicy model // - Each inbox can override the account-level policy // - If no inbox-specific policy exists, the account policy is used type InboxAssignmentPolicy struct { model.Base AccountID uint `gorm:"index;not null" json:"account_id"` InboxID uint `gorm:"uniqueIndex;not null" json:"inbox_id"` Policy AssignmentPolicyType `gorm:"size:50;default:round_robin" json:"policy"` FairDistributionLimit int `gorm:"default:5" json:"fair_distribution_limit"` FairDistributionWindow int `gorm:"default:300" json:"fair_distribution_window"` // seconds Active bool `gorm:"default:true" json:"active"` } func (InboxAssignmentPolicy) TableName() string { return "inbox_assignment_policies" } // EffectivePolicy returns the effective assignment policy for a given inbox. // If the inbox has a specific policy, it is used; otherwise the account policy is used. func EffectivePolicy(accountPolicy *AssignmentPolicy, inboxPolicy *InboxAssignmentPolicy) AssignmentPolicyType { if inboxPolicy != nil && inboxPolicy.Active { return inboxPolicy.Policy } if accountPolicy != nil && accountPolicy.Active { return accountPolicy.Policy } return PolicyRoundRobin // default } // EffectiveLimit returns the effective fair distribution limit for a given inbox. func EffectiveLimit(accountPolicy *AssignmentPolicy, inboxPolicy *InboxAssignmentPolicy) int { if inboxPolicy != nil && inboxPolicy.Active && inboxPolicy.FairDistributionLimit > 0 { return inboxPolicy.FairDistributionLimit } if accountPolicy != nil && accountPolicy.FairDistributionLimit > 0 { return accountPolicy.FairDistributionLimit } return 5 // default } // EffectiveWindow returns the effective fair distribution window (in seconds). func EffectiveWindow(accountPolicy *AssignmentPolicy, inboxPolicy *InboxAssignmentPolicy) int { if inboxPolicy != nil && inboxPolicy.Active && inboxPolicy.FairDistributionWindow > 0 { return inboxPolicy.FairDistributionWindow } if accountPolicy != nil && accountPolicy.FairDistributionWindow > 0 { return accountPolicy.FairDistributionWindow } return 300 // default (5 minutes) }