* feat(conversations): complete manual AI takeover * fix(conversations): align AI takeover flow with channel AI * fix(conversations): close takeover review gaps --------- Co-authored-by: Rogee <rogee@ipao.vip>
62 lines
3.6 KiB
Go
62 lines
3.6 KiB
Go
package model
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"gorm.io/datatypes"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// Conversation represents a conversation between a contact and agents.
|
|
type Conversation struct {
|
|
Base
|
|
UUID string `gorm:"type:uuid;uniqueIndex;not null" json:"uuid"` // auto-generated global unique identifier
|
|
DisplayID *uint `gorm:"index" json:"display_id,omitempty"` // account-level auto-increment number
|
|
AccountID uint `gorm:"index;not null" json:"account_id"`
|
|
InboxID uint `gorm:"index;not null" json:"inbox_id"`
|
|
ContactID uint `gorm:"index;not null" json:"contact_id"`
|
|
ContactInboxID *uint `gorm:"index" json:"contact_inbox_id,omitempty"`
|
|
AssigneeID *uint `gorm:"index" json:"assignee_id"`
|
|
AssigneeAgentBotID *uint `gorm:"index" json:"assignee_agent_bot_id,omitempty"`
|
|
AITakeoverVersion uint `gorm:"not null;default:0" json:"ai_takeover_version"`
|
|
TeamID *uint `gorm:"index" json:"team_id,omitempty"`
|
|
CampaignID *uint `gorm:"index" json:"campaign_id,omitempty"`
|
|
SlaPolicyID *uint `gorm:"index" json:"sla_policy_id,omitempty"`
|
|
Status string `gorm:"size:50;index;default:open" json:"status"` // open, resolved, pending, snoozed
|
|
Priority string `gorm:"size:50;default:none" json:"priority"` // none, low, medium, high, urgent
|
|
ChannelType string `gorm:"size:50;not null" json:"channel_type"`
|
|
Channel string `gorm:"size:50;not null" json:"channel"` // channel identifier for routing
|
|
Labels string `gorm:"type:text" json:"labels,omitempty"` // comma-separated or JSON label list
|
|
SnoozedUntil *int64 `gorm:"index" json:"snoozed_until,omitempty"` // timestamp for snoozed conversations
|
|
AdditionalAttributes datatypes.JSON `gorm:"type:jsonb" json:"additional_attributes,omitempty"`
|
|
CustomAttributes datatypes.JSON `gorm:"type:jsonb" json:"custom_attributes,omitempty"`
|
|
AgentLastSeenAt *int64 `json:"agent_last_seen_at,omitempty"`
|
|
AssigneeLastSeenAt *int64 `json:"assignee_last_seen_at,omitempty"`
|
|
ContactLastSeenAt *int64 `json:"contact_last_seen_at,omitempty"`
|
|
WaitingSince *int64 `json:"waiting_since,omitempty"`
|
|
LastActivityAt *int64 `json:"last_activity_at,omitempty"`
|
|
FirstReplyCreatedAt *int64 `json:"first_reply_created_at,omitempty"`
|
|
Muted bool `gorm:"default:false" json:"muted"`
|
|
ResolvedAt *time.Time `json:"resolved_at,omitempty"` // Chatwoot: timestamp when conversation was resolved
|
|
ResumedAt *time.Time `json:"resumed_at,omitempty"` // Chatwoot: timestamp when conversation was reopened
|
|
LastMessageAt *int64 `gorm:"index" json:"last_message_at,omitempty"`
|
|
LastNonSysMsgAt *int64 `json:"last_non_system_message_at,omitempty"`
|
|
|
|
Contact *Contact `gorm:"foreignKey:ContactID" json:"contact,omitempty"`
|
|
Inbox *Inbox `gorm:"foreignKey:InboxID" json:"inbox,omitempty"`
|
|
Assignee *User `gorm:"foreignKey:AssigneeID" json:"assignee,omitempty"`
|
|
Messages []Message `gorm:"foreignKey:ConversationID" json:"messages,omitempty"`
|
|
}
|
|
|
|
// BeforeCreate auto-generates UUID before inserting a new Conversation record.
|
|
func (c *Conversation) BeforeCreate(tx *gorm.DB) error {
|
|
if c.UUID == "" {
|
|
c.UUID = uuid.New().String()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (Conversation) TableName() string { return "conversations" }
|