models

package
v0.8.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 28, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package models provides domain models and data structures.

Index

Constants

View Source
const (
	TemplateTypeGreeting       = "greeting"
	TemplateTypeSignature      = "signature"
	TemplateTypeAutoReply      = "auto_reply"
	TemplateTypeTicketNew      = "ticket_created"
	TemplateTypeTicketUpdate   = "ticket_updated"
	TemplateTypeTicketAssigned = "ticket_assigned"
	TemplateTypeTicketClosed   = "ticket_closed"
)

Template types.

View Source
const (
	GroupTypeLocal    = "local"
	GroupTypeLDAP     = "ldap"
	GroupTypeExternal = "external"
)

Common group types.

View Source
const (
	GroupRoleMember = "member"
	GroupRoleAdmin  = "admin"
	GroupRoleOwner  = "owner"
)

Common group roles.

View Source
const (
	LDAPSyncStatusPending   = "pending"
	LDAPSyncStatusRunning   = "running"
	LDAPSyncStatusCompleted = "completed"
	LDAPSyncStatusFailed    = "failed"
	LDAPSyncStatusCancelled = "cancelled"
)

Constants for LDAP sync status.

View Source
const (
	LDAPSyncTriggerManual    = "manual"
	LDAPSyncTriggerScheduled = "scheduled"
	LDAPSyncTriggerAPI       = "api"
	LDAPSyncTriggerStartup   = "startup"
)

Constants for LDAP sync triggers.

View Source
const (
	RoleUser  = "user"
	RoleGuest = "guest"
)

Additional role names (RoleAdmin and RoleAgent are defined in user.go).

View Source
const (
	PermissionViewTickets     = "view_tickets"
	PermissionCreateTickets   = "create_tickets"
	PermissionEditTickets     = "edit_tickets"
	PermissionDeleteTickets   = "delete_tickets"
	PermissionAssignTickets   = "assign_tickets"
	PermissionViewAllTickets  = "view_all_tickets"
	PermissionManageUsers     = "manage_users"
	PermissionManageQueues    = "manage_queues"
	PermissionManageSettings  = "manage_settings"
	PermissionViewReports     = "view_reports"
	PermissionManageTemplates = "manage_templates"
	PermissionManageWorkflows = "manage_workflows"
)

Common permissions.

View Source
const (
	SessionKeyUserID          = "UserID"
	SessionKeyUserLogin       = "UserLogin"
	SessionKeyUserType        = "UserType"
	SessionKeyUserTitle       = "UserTitle"
	SessionKeyUserFullname    = "UserFullname" // OTRS uses lowercase 'n'
	SessionKeyCreateTime      = "CreateTime"
	SessionKeyLastRequest     = "LastRequest"
	SessionKeyUserRemoteAddr  = "UserRemoteAddr"
	SessionKeyUserRemoteAgent = "UserRemoteUserAgent"
)

Session data keys (matching OTRS conventions).

View Source
const (
	UserTypeAgent    = "User"
	UserTypeCustomer = "Customer"
)

User type constants.

View Source
const (
	TicketStateNew     = 1
	TicketStateOpen    = 2
	TicketStateClosed  = 3
	TicketStateRemoved = 4
	TicketStatePending = 5
)

Constants for ticket states.

View Source
const (
	TicketUnlocked  = 1
	TicketLocked    = 2
	TicketTmpLocked = 3
)

Constants for ticket lock states.

View Source
const (
	ArticleTypeEmailExternal = 1
	ArticleTypeEmailInternal = 2
	ArticleTypePhone         = 3
	ArticleTypeFax           = 4
	ArticleTypeSMS           = 5
	ArticleTypeWebRequest    = 6
	ArticleTypeNoteInternal  = 7
	ArticleTypeNoteExternal  = 8
)

Constants for article types.

View Source
const (
	SenderTypeAgent    = 1
	SenderTypeSystem   = 2
	SenderTypeCustomer = 3
)

Constants for sender types.

View Source
const DefaultRateLimit = 1000

DefaultRateLimit is the default rate limit for new tokens (requests per hour)

View Source
const TokenPrefix = "gf_"

TokenPrefix is the prefix for all API tokens

View Source
const TokenPrefixLength = 8

TokenPrefixLength is the length of the identifier prefix (after gf_)

View Source
const TokenRandomLength = 32

TokenRandomLength is the length of the random part of the token

Variables

View Source
var PermissionTypes = []string{
	"ro",
	"move_into",
	"create",
	"note",
	"owner",
	"priority",
	"rw",
}

Permission types (OTRS-compatible).

View Source
var ValidScopes = map[string]string{
	"*":              "Full access (inherits all user permissions)",
	"tickets:read":   "View tickets",
	"tickets:write":  "Create and update tickets",
	"tickets:delete": "Delete tickets",
	"articles:read":  "Read ticket articles",
	"articles:write": "Add articles and replies",
	"users:read":     "View user information",
	"queues:read":    "View queue information",
	"admin:*":        "Admin operations (agents only)",
}

ValidScopes defines the allowed scope values

View Source
var ValidTicketAttributes = []string{
	"Queue",
	"State",
	"Priority",
	"Type",
	"Service",
	"SLA",
	"Owner",
	"Responsible",
}

ValidTicketAttributes lists the standard ticket attributes that can be used in relations.

Functions

func DerefString

func DerefString(p *string) string

DerefString safely dereferences a string pointer.

func DerefUint

func DerefUint(p *uint) uint

DerefUint safely dereferences a uint pointer.

func GetDynamicFieldName

func GetDynamicFieldName(attr string) string

GetDynamicFieldName extracts the field name from a "DynamicField_Name" attribute.

func IsDynamicFieldAttribute

func IsDynamicFieldAttribute(attr string) bool

IsDynamicFieldAttribute returns true if the attribute is a dynamic field reference.

func IsScopeAllowed

func IsScopeAllowed(scope string, userRole string, isCustomer bool) bool

IsScopeAllowed checks if a scope is allowed for a given user context

func IsValidAttribute

func IsValidAttribute(attr string) bool

IsValidAttribute checks if an attribute name is valid for ticket attribute relations. Valid attributes are either standard ticket attributes or dynamic fields (prefixed with "DynamicField_").

func IsValidScope

func IsValidScope(scope string) bool

IsValidScope checks if a scope is valid (exists in registry)

func NullableString

func NullableString(v string) *string

NullableString converts a string to a nullable string for database operations.

func NullableUint

func NullableUint(v uint) *uint

NullableUint converts a uint to a nullable uint for database operations.

func RegisterScope

func RegisterScope(def *ScopeDefinition)

RegisterScope adds a scope to the registry (used by plugins)

func UnregisterScope

func UnregisterScope(scope string)

UnregisterScope removes a scope (used when plugins unload)

func ValidateArticleType

func ValidateArticleType(typeID int) bool

ValidateArticleType validates that an article type ID is valid.

func ValidateSenderType

func ValidateSenderType(typeID int) bool

ValidateSenderType validates that a sender type ID is valid.

func ValidateTicketLock

func ValidateTicketLock(lockID int) bool

ValidateTicketLock validates that a lock ID is valid.

func ValidateTicketState

func ValidateTicketState(stateID uint) bool

ValidateTicketState validates that a state ID is valid.

Types

type ACL

type ACL struct {
	ID             int              `json:"id"`
	Name           string           `json:"name"`
	Comments       *string          `json:"comments,omitempty"`
	Description    *string          `json:"description,omitempty"`
	ValidID        int              `json:"valid_id"`
	StopAfterMatch bool             `json:"stop_after_match"`
	ConfigMatch    *ACLConfigMatch  `json:"config_match,omitempty"`
	ConfigChange   *ACLConfigChange `json:"config_change,omitempty"`
	CreateTime     time.Time        `json:"create_time"`
	CreateBy       int              `json:"create_by"`
	ChangeTime     time.Time        `json:"change_time"`
	ChangeBy       int              `json:"change_by"`
}

ACL represents an Access Control List entry.

func (*ACL) HasChange

func (a *ACL) HasChange() bool

HasChange returns true if the ACL has any change rules defined.

func (*ACL) HasMatch

func (a *ACL) HasMatch() bool

HasMatch returns true if the ACL has any match conditions defined.

func (*ACL) IsValid

func (a *ACL) IsValid() bool

IsValid returns true if the ACL is enabled (valid_id = 1).

type ACLConfigChange

type ACLConfigChange struct {
	// Possible is a whitelist - ONLY these values are allowed
	Possible map[string]map[string][]string `json:"Possible,omitempty"`
	// PossibleAdd adds these values to the current options
	PossibleAdd map[string]map[string][]string `json:"PossibleAdd,omitempty"`
	// PossibleNot is a blacklist - these values are removed
	PossibleNot map[string]map[string][]string `json:"PossibleNot,omitempty"`
}

ACLConfigChange defines what changes the ACL makes to available options.

type ACLConfigMatch

type ACLConfigMatch struct {
	// Properties matches against current form/frontend values
	Properties map[string]map[string][]string `json:"Properties,omitempty"`
	// PropertiesDatabase matches against values from the database
	PropertiesDatabase map[string]map[string][]string `json:"PropertiesDatabase,omitempty"`
}

ACLConfigMatch defines the conditions for when an ACL applies. Matches against current ticket/form values (Properties) or database values (PropertiesDatabase).

type ACLContext

type ACLContext struct {
	// User context
	UserID         int
	CustomerUserID string

	// Ticket context (from database for PropertiesDatabase matching)
	TicketID   int
	Ticket     *Ticket
	QueueID    int
	StateID    int
	PriorityID int
	TypeID     int
	ServiceID  int
	SLAID      int
	OwnerID    int
	LockID     int
	CustomerID string

	// Frontend/Form context (for Properties matching)
	// These represent current form values that may differ from DB
	FormQueueID    *int
	FormStateID    *int
	FormPriorityID *int
	FormTypeID     *int
	FormServiceID  *int
	FormSLAID      *int
	FormOwnerID    *int
	FormLockID     *int

	// Dynamic fields
	DynamicFields map[string]interface{}

	// Action context (which action/screen is being used)
	Action string
	// Frontend indicates whether to match frontend/form values
	Frontend bool
}

ACLContext provides the context for ACL evaluation.

type ACLResult

type ACLResult struct {
	// MatchedACLs contains the names of ACLs that matched
	MatchedACLs []string
	// Allowed contains IDs that are allowed (from Possible rules)
	Allowed map[string][]int
	// Denied contains IDs that are denied (from PossibleNot rules)
	Denied map[string][]int
	// Added contains IDs that were added (from PossibleAdd rules)
	Added map[string][]int
}

ACLResult contains the result of ACL evaluation.

func NewACLResult

func NewACLResult() *ACLResult

NewACLResult creates a new empty ACL result.

type APIToken

type APIToken struct {
	ID            int64            `json:"id" db:"id"`
	UserID        int              `json:"user_id" db:"user_id"`
	UserType      APITokenUserType `json:"user_type" db:"user_type"`
	Name          string           `json:"name" db:"name"`
	Prefix        string           `json:"prefix" db:"prefix"`
	TokenHash     string           `json:"-" db:"token_hash"` // Never expose hash
	Scopes        []string         `json:"scopes,omitempty"`  // Parsed from JSON
	ScopesJSON    sql.NullString   `json:"-" db:"scopes"`     // Raw JSON from DB
	ExpiresAt     sql.NullTime     `json:"expires_at,omitempty" db:"expires_at"`
	LastUsedAt    sql.NullTime     `json:"last_used_at,omitempty" db:"last_used_at"`
	LastUsedIP    sql.NullString   `json:"last_used_ip,omitempty" db:"last_used_ip"`
	RateLimit     int              `json:"rate_limit" db:"rate_limit"`
	CreatedAt     time.Time        `json:"created_at" db:"created_at"`
	CreatedBy     sql.NullInt64    `json:"created_by,omitempty" db:"created_by"`
	RevokedAt     sql.NullTime     `json:"revoked_at,omitempty" db:"revoked_at"`
	RevokedBy     sql.NullInt64    `json:"revoked_by,omitempty" db:"revoked_by"`
	CustomerLogin string           `json:"customer_login,omitempty"` // For customer tokens: login from customer_user
}

APIToken represents a personal access token for API authentication

func (*APIToken) HasScope

func (t *APIToken) HasScope(scope string) bool

HasScope returns true if the token has the specified scope If scopes is nil/empty, token has all permissions (inherits from user)

func (*APIToken) IsActive

func (t *APIToken) IsActive() bool

IsActive returns true if the token is valid for use

func (*APIToken) IsExpired

func (t *APIToken) IsExpired() bool

IsExpired returns true if the token has expired

func (*APIToken) IsRevoked

func (t *APIToken) IsRevoked() bool

IsRevoked returns true if the token has been revoked

type APITokenCreateRequest

type APITokenCreateRequest struct {
	Name      string   `json:"name" binding:"required,min=1,max=100"`
	Scopes    []string `json:"scopes,omitempty"`
	ExpiresIn string   `json:"expires_in,omitempty"` // "30d", "90d", "1y", "never"
}

APITokenCreateRequest represents a request to create a new token

type APITokenCreateResponse

type APITokenCreateResponse struct {
	ID        int64     `json:"id"`
	Name      string    `json:"name"`
	Prefix    string    `json:"prefix"`
	Token     string    `json:"token"` // Full token - shown only at creation
	Scopes    []string  `json:"scopes,omitempty"`
	ExpiresAt *string   `json:"expires_at,omitempty"`
	CreatedAt time.Time `json:"created_at"`
	Warning   string    `json:"warning"`
}

APITokenCreateResponse includes the full token (shown only once)

type APITokenListItem

type APITokenListItem struct {
	ID         int64    `json:"id"`
	Name       string   `json:"name"`
	Prefix     string   `json:"prefix"`
	Scopes     []string `json:"scopes,omitempty"`
	ExpiresAt  *string  `json:"expires_at,omitempty"`
	LastUsedAt *string  `json:"last_used_at,omitempty"`
	CreatedAt  string   `json:"created_at"`
	IsActive   bool     `json:"is_active"`
}

APITokenListItem represents a token in list responses (no secret)

type APITokenUserType

type APITokenUserType string

APITokenUserType represents the type of user for API tokens

const (
	APITokenUserAgent    APITokenUserType = "agent"
	APITokenUserCustomer APITokenUserType = "customer"
)

type Action

type Action struct {
	ID            int             `json:"id"`
	WorkflowID    int             `json:"workflow_id"`
	Type          ActionType      `json:"type"`
	Config        json.RawMessage `json:"config"` // Action-specific configuration
	Order         int             `json:"order"`  // Execution order
	ContinueOnErr bool            `json:"continue_on_error"`
	DelaySeconds  int             `json:"delay_seconds"` // Delay before executing
}

Action represents a workflow action.

type ActionConfig

type ActionConfig struct {
	// For assignment actions
	AssignToUserID   int    `json:"assign_to_user_id,omitempty"`
	AssignToGroupID  int    `json:"assign_to_group_id,omitempty"`
	AssignmentMethod string `json:"assignment_method,omitempty"` // round_robin, least_loaded, skills_based

	// For status/priority changes
	NewStatus   string `json:"new_status,omitempty"`
	NewPriority string `json:"new_priority,omitempty"`

	// For email actions
	EmailTo         []string `json:"email_to,omitempty"`
	EmailCC         []string `json:"email_cc,omitempty"`
	EmailSubject    string   `json:"email_subject,omitempty"`
	EmailBody       string   `json:"email_body,omitempty"`
	EmailTemplateID int      `json:"email_template_id,omitempty"`

	// For notification actions
	NotifyUserIDs    []int  `json:"notify_user_ids,omitempty"`
	NotifyGroupIDs   []int  `json:"notify_group_ids,omitempty"`
	NotificationText string `json:"notification_text,omitempty"`

	// For tag actions
	Tags []string `json:"tags,omitempty"`

	// For note actions
	NoteContent    string `json:"note_content,omitempty"`
	NoteIsInternal bool   `json:"note_is_internal,omitempty"`

	// For webhook actions
	WebhookURL     string            `json:"webhook_url,omitempty"`
	WebhookMethod  string            `json:"webhook_method,omitempty"`
	WebhookHeaders map[string]string `json:"webhook_headers,omitempty"`
	WebhookBody    string            `json:"webhook_body,omitempty"`

	// For script actions
	ScriptCommand string   `json:"script_command,omitempty"`
	ScriptArgs    []string `json:"script_args,omitempty"`
	ScriptTimeout int      `json:"script_timeout_seconds,omitempty"`

	// For custom field updates
	CustomFieldName  string      `json:"custom_field_name,omitempty"`
	CustomFieldValue interface{} `json:"custom_field_value,omitempty"`
}

ActionConfig represents action-specific configuration.

type ActionType

type ActionType string

ActionType represents the type of action in a workflow.

const (
	ActionTypeAssignTicket      ActionType = "assign_ticket"
	ActionTypeChangeStatus      ActionType = "change_status"
	ActionTypeChangePriority    ActionType = "change_priority"
	ActionTypeSendEmail         ActionType = "send_email"
	ActionTypeSendNotification  ActionType = "send_notification"
	ActionTypeAddTag            ActionType = "add_tag"
	ActionTypeRemoveTag         ActionType = "remove_tag"
	ActionTypeAddNote           ActionType = "add_note"
	ActionTypeEscalate          ActionType = "escalate"
	ActionTypeRunScript         ActionType = "run_script"
	ActionTypeWebhookCall       ActionType = "webhook_call"
	ActionTypeCreateTicket      ActionType = "create_ticket"
	ActionTypeMergeTicket       ActionType = "merge_ticket"
	ActionTypeSetSLA            ActionType = "set_sla"
	ActionTypeUpdateCustomField ActionType = "update_custom_field"
)

type AppliedResponse

type AppliedResponse struct {
	Subject     string   `json:"subject"`
	Content     string   `json:"content"`
	ContentType string   `json:"content_type"`
	Attachments []string `json:"attachments,omitempty"`
	AsInternal  bool     `json:"as_internal"`
}

AppliedResponse represents the result of applying a canned response.

type Article

type Article struct {
	ID                     int         `json:"id" db:"id"`
	TicketID               int         `json:"ticket_id" db:"ticket_id"`
	ArticleTypeID          int         `json:"article_type_id" db:"article_type_id"` // 1=email-external, 2=email-internal, etc.
	SenderTypeID           int         `json:"sender_type_id" db:"sender_type_id"`   // 1=agent, 2=system, 3=customer
	CommunicationChannelID int         `json:"communication_channel_id" db:"communication_channel_id"`
	IsVisibleForCustomer   int         `json:"is_visible_for_customer" db:"is_visible_for_customer"`
	Subject                string      `json:"subject" db:"subject"`
	Body                   interface{} `json:"body" db:"body"`                         // Can be string or []byte
	BodyType               string      `json:"body_type" db:"body_type"`               // text/plain, text/html
	TemplateID             *uint       `json:"template_id,omitempty" db:"template_id"` // Track which template was used
	Charset                string      `json:"charset" db:"charset"`
	MimeType               string      `json:"mime_type" db:"mime_type"`
	ContentPath            *string     `json:"content_path,omitempty" db:"content_path"`
	MessageID              string      `json:"message_id" db:"message_id"`   // Email Message-ID header
	InReplyTo              string      `json:"in_reply_to" db:"in_reply_to"` // Email In-Reply-To header
	References             string      `json:"references" db:"references"`   // Email References header
	ValidID                int         `json:"valid_id" db:"valid_id"`
	CreateTime             time.Time   `json:"create_time" db:"create_time"`
	CreateBy               int         `json:"create_by" db:"create_by"`
	ChangeTime             time.Time   `json:"change_time" db:"change_time"`
	ChangeBy               int         `json:"change_by" db:"change_by"`

	// Joined fields
	Ticket      *Ticket      `json:"ticket,omitempty"`
	Creator     *User        `json:"creator,omitempty"`
	Attachments []Attachment `json:"attachments,omitempty"`
}

Article represents a message/comment within a ticket.

type ArticleAttachment

type ArticleAttachment struct {
	ID                 int       `json:"id" db:"id"`
	ArticleID          int       `json:"article_id" db:"article_id"`
	Filename           string    `json:"filename" db:"filename"`
	ContentType        string    `json:"content_type" db:"content_type"`
	ContentSize        int       `json:"content_size" db:"content_size"`
	ContentID          *string   `json:"content_id,omitempty" db:"content_id"`
	ContentAlternative *string   `json:"content_alternative,omitempty" db:"content_alternative"`
	Disposition        string    `json:"disposition" db:"disposition"`
	Content            string    `json:"content" db:"content"` // Base64 encoded or file path
	CreateTime         time.Time `json:"create_time" db:"create_time"`
	CreateBy           int       `json:"create_by" db:"create_by"`
	ChangeTime         time.Time `json:"change_time" db:"change_time"`
	ChangeBy           int       `json:"change_by" db:"change_by"`
}

ArticleAttachment represents a file attachment to an article.

type ArticleComment

type ArticleComment struct {
	ID        uint              `json:"id" gorm:"primaryKey"`
	ArticleID uint              `json:"article_id" gorm:"not null"`
	Article   *KnowledgeArticle `json:"article,omitempty" gorm:"foreignKey:ArticleID"`
	AuthorID  uint              `json:"author_id" gorm:"not null"`
	Author    *User             `json:"author,omitempty" gorm:"foreignKey:AuthorID"`
	Comment   string            `json:"comment" gorm:"not null"`
	IsPublic  bool              `json:"is_public" gorm:"default:true"`
	IsHelpful *bool             `json:"is_helpful"`
	ParentID  *uint             `json:"parent_id"`
	Parent    *ArticleComment   `json:"parent,omitempty" gorm:"foreignKey:ParentID"`
	Replies   []ArticleComment  `json:"replies,omitempty" gorm:"foreignKey:ParentID"`
	CreatedAt time.Time         `json:"created_at"`
	UpdatedAt time.Time         `json:"updated_at"`
}

ArticleComment represents a comment on a knowledge article.

type ArticleCreateRequest

type ArticleCreateRequest struct {
	TicketID             uint     `json:"ticket_id" binding:"required"`
	ArticleTypeID        int      `json:"article_type_id,omitempty"` // defaults to note-internal
	SenderTypeID         int      `json:"sender_type_id,omitempty"`  // defaults based on user role
	IsVisibleForCustomer int      `json:"is_visible_for_customer,omitempty"`
	Subject              *string  `json:"subject,omitempty"`
	Body                 string   `json:"body" binding:"required"`
	BodyType             string   `json:"body_type,omitempty"`   // defaults to text/plain
	Attachments          []string `json:"attachments,omitempty"` // Base64 encoded files
}

ArticleCreateRequest represents a request to add an article to a ticket.

type ArticleFeedback

type ArticleFeedback struct {
	ID         uint              `json:"id" gorm:"primaryKey"`
	ArticleID  uint              `json:"article_id" gorm:"not null"`
	Article    *KnowledgeArticle `json:"article,omitempty" gorm:"foreignKey:ArticleID"`
	UserID     uint              `json:"user_id" gorm:"not null"`
	User       *User             `json:"user,omitempty" gorm:"foreignKey:UserID"`
	IsHelpful  bool              `json:"is_helpful"`
	Rating     int               `json:"rating"` // 1-5 scale
	Feedback   string            `json:"feedback"`
	Suggestion string            `json:"suggestion"`
	CreatedAt  time.Time         `json:"created_at"`
	UpdatedAt  time.Time         `json:"updated_at"`
}

ArticleFeedback represents user feedback on an article.

type ArticleHistory

type ArticleHistory struct {
	ID          uint              `json:"id" gorm:"primaryKey"`
	ArticleID   uint              `json:"article_id" gorm:"not null"`
	Article     *KnowledgeArticle `json:"article,omitempty" gorm:"foreignKey:ArticleID"`
	Version     int               `json:"version"`
	Title       string            `json:"title"`
	Content     string            `json:"content" gorm:"type:text"`
	Summary     string            `json:"summary"`
	ChangedByID uint              `json:"changed_by_id" gorm:"not null"`
	ChangedBy   *User             `json:"changed_by,omitempty" gorm:"foreignKey:ChangedByID"`
	ChangeType  string            `json:"change_type"` // create, update, publish, archive
	ChangeNotes string            `json:"change_notes"`
	CreatedAt   time.Time         `json:"created_at"`
}

ArticleHistory tracks changes to articles.

type ArticleStatus

type ArticleStatus string

ArticleStatus represents the status of a knowledge article.

const (
	ArticleStatusDraft     ArticleStatus = "draft"
	ArticleStatusReview    ArticleStatus = "review"
	ArticleStatusApproved  ArticleStatus = "approved"
	ArticleStatusPublished ArticleStatus = "published"
	ArticleStatusArchived  ArticleStatus = "archived"
	ArticleStatusRetired   ArticleStatus = "retired"
)

type ArticleType

type ArticleType string

ArticleType represents the type of knowledge article.

const (
	ArticleTypeFAQ             ArticleType = "faq"
	ArticleTypeHowTo           ArticleType = "how_to"
	ArticleTypeTroubleshooting ArticleType = "troubleshooting"
	ArticleTypeReference       ArticleType = "reference"
	ArticleTypePolicy          ArticleType = "policy"
	ArticleTypeProcedure       ArticleType = "procedure"
	ArticleTypeAnnouncement    ArticleType = "announcement"
	ArticleTypeKnownError      ArticleType = "known_error"
)

type ArticleView

type ArticleView struct {
	ID           uint              `json:"id" gorm:"primaryKey"`
	ArticleID    uint              `json:"article_id" gorm:"not null;index"`
	Article      *KnowledgeArticle `json:"article,omitempty" gorm:"foreignKey:ArticleID"`
	UserID       *uint             `json:"user_id"`
	User         *User             `json:"user,omitempty" gorm:"foreignKey:UserID"`
	SessionID    string            `json:"session_id"`
	IPAddress    string            `json:"ip_address"`
	UserAgent    string            `json:"user_agent"`
	Referrer     string            `json:"referrer"`
	SearchQuery  string            `json:"search_query"`
	ViewDuration int               `json:"view_duration"` // Seconds
	CreatedAt    time.Time         `json:"created_at"`
}

ArticleView tracks article views for analytics.

type ArticleVisibility

type ArticleVisibility string

ArticleVisibility represents who can see the article.

const (
	VisibilityPublic     ArticleVisibility = "public"     // Everyone including customers
	VisibilityInternal   ArticleVisibility = "internal"   // Internal staff only
	VisibilityRestricted ArticleVisibility = "restricted" // Specific groups only
)

type AssignTicketRequest

type AssignTicketRequest struct {
	AgentID uint `json:"agent_id" binding:"required"`
}

AssignTicketRequest represents a request to assign a ticket.

type Attachment

type Attachment struct {
	ID                 uint      `json:"id" db:"id"`
	ArticleID          uint      `json:"article_id" db:"article_id"`
	Filename           string    `json:"filename" db:"filename"`
	ContentType        string    `json:"content_type" db:"content_type"`
	ContentSize        int       `json:"content_size" db:"content_size"`
	ContentID          *string   `json:"content_id,omitempty" db:"content_id"`
	ContentAlternative *string   `json:"content_alternative,omitempty" db:"content_alternative"`
	Disposition        string    `json:"disposition" db:"disposition"`
	Content            string    `json:"content" db:"content"` // Base64 encoded or file path
	CreateTime         time.Time `json:"create_time" db:"create_time"`
	CreateBy           uint      `json:"create_by" db:"create_by"`
	ChangeTime         time.Time `json:"change_time" db:"change_time"`
	ChangeBy           uint      `json:"change_by" db:"change_by"`
}

Attachment represents a file attachment to an article.

type AttributeRelationPair

type AttributeRelationPair struct {
	Attribute1Value string `json:"attr1_value"`
	Attribute2Value string `json:"attr2_value"`
}

AttributeRelationPair represents a single mapping between attribute values.

type AuthConfig

type AuthConfig struct {
	AuthType string `yaml:"AuthType,omitempty" json:"auth_type,omitempty"` // BasicAuth, JWT, OAuth2, APIKey

	// Basic Auth
	BasicAuthUser     string `yaml:"BasicAuthUser,omitempty" json:"basic_auth_user,omitempty"`
	BasicAuthPassword string `yaml:"BasicAuthPassword,omitempty" json:"basic_auth_password,omitempty"`

	// API Key
	APIKey       string `yaml:"APIKey,omitempty" json:"api_key,omitempty"`
	APIKeyHeader string `yaml:"APIKeyHeader,omitempty" json:"api_key_header,omitempty"` // Header name, defaults to X-API-Key

	// OAuth2
	OAuth2TokenURL     string `yaml:"OAuth2TokenURL,omitempty" json:"oauth2_token_url,omitempty"`
	OAuth2ClientID     string `yaml:"OAuth2ClientID,omitempty" json:"oauth2_client_id,omitempty"`
	OAuth2ClientSecret string `yaml:"OAuth2ClientSecret,omitempty" json:"oauth2_client_secret,omitempty"`
	OAuth2Scope        string `yaml:"OAuth2Scope,omitempty" json:"oauth2_scope,omitempty"`

	// JWT
	JWTAuthKeyFilePath          string `yaml:"JWTAuthKeyFilePath,omitempty" json:"jwt_auth_key_file_path,omitempty"`
	JWTAuthKeyFilePassword      string `yaml:"JWTAuthKeyFilePassword,omitempty" json:"jwt_auth_key_file_password,omitempty"`
	JWTAuthAlgorithm            string `yaml:"JWTAuthAlgorithm,omitempty" json:"jwt_auth_algorithm,omitempty"`
	JWTAuthCertificateFilePath  string `yaml:"JWTAuthCertificateFilePath,omitempty" json:"jwt_auth_certificate_file_path,omitempty"`
	JWTAuthTTL                  string `yaml:"JWTAuthTTL,omitempty" json:"jwt_auth_ttl,omitempty"`
	JWTAuthPayload              string `yaml:"JWTAuthPayload,omitempty" json:"jwt_auth_payload,omitempty"`
	JWTAuthAdditionalHeaderData string `yaml:"JWTAuthAdditionalHeaderData,omitempty" json:"jwt_auth_additional_header_data,omitempty"`
}

AuthConfig defines authentication settings.

type AutoFillContext

type AutoFillContext struct {
	AgentName     string `json:"agent_name,omitempty"`
	AgentEmail    string `json:"agent_email,omitempty"`
	TicketNumber  string `json:"ticket_number,omitempty"`
	CustomerName  string `json:"customer_name,omitempty"`
	CustomerEmail string `json:"customer_email,omitempty"`
	QueueName     string `json:"queue_name,omitempty"`
}

AutoFillContext provides context for auto-filling variables.

type BreachReason

type BreachReason struct {
	Reason  string  `json:"reason"`
	Count   int     `json:"count"`
	Percent float64 `json:"percent"`
}

BreachReason represents reasons for SLA breaches.

type BusinessCalendar

type BusinessCalendar struct {
	ID           uint           `json:"id"`
	Name         string         `json:"name" binding:"required"`
	Description  string         `json:"description"`
	TimeZone     string         `json:"time_zone" binding:"required"`
	WorkingHours []WorkingHours `json:"working_hours"`
	Holidays     []SLAHoliday   `json:"holidays,omitempty"`
	IsDefault    bool           `json:"is_default"`
	CreatedAt    time.Time      `json:"created_at"`
	UpdatedAt    time.Time      `json:"updated_at"`
}

BusinessCalendar defines working hours and holidays (SLA data model).

type BusinessException

type BusinessException struct {
	ID        int       `json:"id"`
	ConfigID  int       `json:"config_id"`
	Name      string    `json:"name"`
	Date      time.Time `json:"date"`
	IsWorking bool      `json:"is_working"` // Override to working/non-working
	StartTime string    `json:"start_time,omitempty"`
	EndTime   string    `json:"end_time,omitempty"`
	Reason    string    `json:"reason"`
}

BusinessException represents an exception to normal business hours.

type BusinessHoursCalculator

type BusinessHoursCalculator struct {
	Config *BusinessHoursConfig
	// contains filtered or unexported fields
}

BusinessHoursCalculator provides business hours calculations.

func NewBusinessHoursCalculator

func NewBusinessHoursCalculator(config *BusinessHoursConfig) (*BusinessHoursCalculator, error)

NewBusinessHoursCalculator creates a new business hours calculator.

func (*BusinessHoursCalculator) AddBusinessHours

func (bc *BusinessHoursCalculator) AddBusinessHours(from time.Time, hours float64) time.Time

AddBusinessHours adds business hours to a given time.

func (*BusinessHoursCalculator) GetBusinessHoursBetween

func (bc *BusinessHoursCalculator) GetBusinessHoursBetween(start, end time.Time) float64

GetBusinessHoursBetween calculates business hours between two times.

func (*BusinessHoursCalculator) GetNextBusinessDay

func (bc *BusinessHoursCalculator) GetNextBusinessDay(from time.Time) time.Time

GetNextBusinessDay returns the next business day from the given date.

func (*BusinessHoursCalculator) GetNextBusinessHour

func (bc *BusinessHoursCalculator) GetNextBusinessHour(from time.Time) time.Time

GetNextBusinessHour returns the next business hour from the given time.

func (*BusinessHoursCalculator) IsBusinessDay

func (bc *BusinessHoursCalculator) IsBusinessDay(date time.Time) bool

IsBusinessDay checks if a given date is a business day.

func (*BusinessHoursCalculator) IsWithinBusinessHours

func (bc *BusinessHoursCalculator) IsWithinBusinessHours(t time.Time) bool

IsWithinBusinessHours checks if a given time is within business hours.

type BusinessHoursConfig

type BusinessHoursConfig struct {
	ID          int                 `json:"id"`
	Name        string              `json:"name"`
	Description string              `json:"description"`
	Timezone    string              `json:"timezone"` // e.g., "America/New_York"
	IsDefault   bool                `json:"is_default"`
	IsActive    bool                `json:"is_active"`
	WorkingDays []WorkingDay        `json:"working_days"`
	Holidays    []Holiday           `json:"holidays"`
	Exceptions  []BusinessException `json:"exceptions"`
	CreatedAt   time.Time           `json:"created_at"`
	UpdatedAt   time.Time           `json:"updated_at"`
}

BusinessHoursConfig represents business hours configuration.

func Get24x7BusinessHours

func Get24x7BusinessHours() *BusinessHoursConfig

Get24x7BusinessHours returns a 24x7 business hours configuration.

func GetDefaultBusinessHours

func GetDefaultBusinessHours() *BusinessHoursConfig

GetDefaultBusinessHours returns a default business hours configuration.

type CIEnvironment

type CIEnvironment string

CIEnvironment represents the environment of a CI.

const (
	CIEnvironmentProduction  CIEnvironment = "production"
	CIEnvironmentStaging     CIEnvironment = "staging"
	CIEnvironmentDevelopment CIEnvironment = "development"
	CIEnvironmentTesting     CIEnvironment = "testing"
	CIEnvironmentDR          CIEnvironment = "disaster_recovery"
)

type CIHistory

type CIHistory struct {
	ID              uint               `json:"id" gorm:"primaryKey"`
	CIID            uint               `json:"ci_id" gorm:"not null;index"`
	CI              *ConfigurationItem `json:"ci,omitempty" gorm:"foreignKey:CIID"`
	FieldName       string             `json:"field_name" gorm:"not null"`
	OldValue        string             `json:"old_value"`
	NewValue        string             `json:"new_value"`
	ChangeType      string             `json:"change_type"` // create, update, delete
	ChangedByID     uint               `json:"changed_by_id" gorm:"not null"`
	ChangedBy       *User              `json:"changed_by,omitempty" gorm:"foreignKey:ChangedByID"`
	ChangeReason    string             `json:"change_reason"`
	ChangeTicketRef string             `json:"change_ticket_ref"`
	CreatedAt       time.Time          `json:"created_at"`
}

CIHistory tracks changes to configuration items.

type CIListRequest

type CIListRequest struct {
	Page        int           `json:"page" form:"page"`
	PerPage     int           `json:"per_page" form:"per_page"`
	Type        CIType        `json:"type" form:"type"`
	Status      CIStatus      `json:"status" form:"status"`
	Environment CIEnvironment `json:"environment" form:"environment"`
	OwnerID     uint          `json:"owner_id" form:"owner_id"`
	Location    string        `json:"location" form:"location"`
	Search      string        `json:"search" form:"search"`
	SortBy      string        `json:"sort_by" form:"sort_by"`
	SortOrder   string        `json:"sort_order" form:"sort_order"`
}

CIListRequest represents a request to list configuration items.

type CIListResponse

type CIListResponse struct {
	ConfigurationItems []*ConfigurationItem `json:"configuration_items"`
	Total              int64                `json:"total"`
	Page               int                  `json:"page"`
	PerPage            int                  `json:"per_page"`
	TotalPages         int                  `json:"total_pages"`
}

CIListResponse represents a response containing a list of configuration items.

type CIRelationship

type CIRelationship struct {
	ID           uint               `json:"id" gorm:"primaryKey"`
	SourceCIID   uint               `json:"source_ci_id" gorm:"not null"`
	SourceCI     *ConfigurationItem `json:"source_ci,omitempty" gorm:"foreignKey:SourceCIID"`
	TargetCIID   uint               `json:"target_ci_id" gorm:"not null"`
	TargetCI     *ConfigurationItem `json:"target_ci,omitempty" gorm:"foreignKey:TargetCIID"`
	RelationType string             `json:"relation_type"` // depends_on, connects_to, runs_on, uses, etc.
	Description  string             `json:"description"`
	IsActive     bool               `json:"is_active" gorm:"default:true"`
	CreatedAt    time.Time          `json:"created_at"`
	UpdatedAt    time.Time          `json:"updated_at"`
}

CIRelationship represents relationships between configuration items.

type CIStatus

type CIStatus string

CIStatus represents the status of a configuration item.

const (
	CIStatusActive        CIStatus = "active"
	CIStatusInactive      CIStatus = "inactive"
	CIStatusRetired       CIStatus = "retired"
	CIStatusDisposed      CIStatus = "disposed"
	CIStatusInMaintenance CIStatus = "in_maintenance"
	CIStatusInStorage     CIStatus = "in_storage"
	CIStatusOrdered       CIStatus = "ordered"
	CIStatusInTransit     CIStatus = "in_transit"
)

type CIType

type CIType string

CIType represents the type of configuration item.

const (
	CITypeServer         CIType = "server"
	CITypeWorkstation    CIType = "workstation"
	CITypeNetwork        CIType = "network"
	CITypeStorage        CIType = "storage"
	CITypeSoftware       CIType = "software"
	CITypeApplication    CIType = "application"
	CITypeDatabase       CIType = "database"
	CITypeService        CIType = "service"
	CITypeVirtualMachine CIType = "virtual_machine"
	CITypeContainer      CIType = "container"
	CITypePrinter        CIType = "printer"
	CITypeMobile         CIType = "mobile"
	CITypeOther          CIType = "other"
)

type CannedResponse

type CannedResponse struct {
	ID          uint      `json:"id"`
	Name        string    `json:"name" binding:"required"`     // Display name for the response
	Shortcut    string    `json:"shortcut"`                    // Quick access code (e.g., "/greeting")
	Category    string    `json:"category" binding:"required"` // Category for organization
	Subject     string    `json:"subject"`                     // Optional subject line
	Content     string    `json:"content" binding:"required"`  // The response content
	ContentType string    `json:"content_type"`                // text/plain or text/html
	Tags        []string  `json:"tags"`                        // Tags for search/filter
	IsPublic    bool      `json:"is_public"`                   // Available to all agents
	IsActive    bool      `json:"is_active"`                   // Currently active
	UsageCount  int       `json:"usage_count"`                 // Track usage
	CreatedBy   uint      `json:"created_by"`
	UpdatedBy   uint      `json:"updated_by"`
	CreatedAt   time.Time `json:"created_at"`
	UpdatedAt   time.Time `json:"updated_at"`

	// Access control
	OwnerID    uint   `json:"owner_id"`              // User who owns this response
	SharedWith []uint `json:"shared_with,omitempty"` // User IDs who can use this
	QueueIDs   []uint `json:"queue_ids,omitempty"`   // Restrict to specific queues

	// Variables for substitution
	Variables []ResponseVariable `json:"variables,omitempty"`

	// Attachments to include
	AttachmentURLs []string `json:"attachment_urls,omitempty"`
}

CannedResponse represents a pre-written response for quick replies.

type CannedResponseApplication

type CannedResponseApplication struct {
	ResponseID uint              `json:"response_id" binding:"required"`
	TicketID   uint              `json:"ticket_id" binding:"required"`
	Variables  map[string]string `json:"variables,omitempty"`
	AsInternal bool              `json:"as_internal"` // Send as internal note vs customer reply
}

CannedResponseApplication for applying a response to a ticket.

type CannedResponseCategory

type CannedResponseCategory struct {
	ID          uint   `json:"id"`
	Name        string `json:"name"`
	Description string `json:"description"`
	Icon        string `json:"icon,omitempty"`
	Order       int    `json:"order"`
	ParentID    *uint  `json:"parent_id,omitempty"` // For nested categories
	Active      bool   `json:"active"`
}

CannedResponseCategory represents a category for organizing responses.

type CannedResponseFilter

type CannedResponseFilter struct {
	Query      string   `json:"query,omitempty"`
	Category   string   `json:"category,omitempty"`
	Tags       []string `json:"tags,omitempty"`
	QueueID    uint     `json:"queue_id,omitempty"`
	OnlyPublic bool     `json:"only_public,omitempty"`
	OnlyOwned  bool     `json:"only_owned,omitempty"`
	UserID     uint     `json:"user_id,omitempty"`
	Limit      int      `json:"limit,omitempty"`
	Offset     int      `json:"offset,omitempty"`
}

CannedResponseFilter for searching/filtering responses.

type CannedResponseUsage

type CannedResponseUsage struct {
	ID             uint      `json:"id"`
	ResponseID     uint      `json:"response_id"`
	TicketID       uint      `json:"ticket_id"`
	UserID         uint      `json:"user_id"`
	UsedAt         time.Time `json:"used_at"`
	ModifiedBefore bool      `json:"modified_before_use"` // Track if agent modified before sending
}

CannedResponseUsage tracks when and where a response was used.

type Change

type Change struct {
	ID           uint         `json:"id" gorm:"primaryKey"`
	ChangeNumber string       `json:"change_number" gorm:"uniqueIndex;not null"`
	Title        string       `json:"title" gorm:"not null"`
	Description  string       `json:"description"`
	Type         ChangeType   `json:"type" gorm:"not null;default:'normal'"`
	Status       ChangeStatus `json:"status" gorm:"not null;default:'draft'"`
	Priority     int          `json:"priority" gorm:"default:3"` // 1-5 scale
	Risk         ChangeRisk   `json:"risk" gorm:"not null;default:'medium'"`
	Impact       ChangeImpact `json:"impact" gorm:"not null;default:'minor'"`
	Category     string       `json:"category"`
	SubCategory  string       `json:"sub_category"`

	// Justification and planning
	BusinessJustification string `json:"business_justification"`
	TechnicalDetails      string `json:"technical_details"`
	ImplementationPlan    string `json:"implementation_plan"`
	TestPlan              string `json:"test_plan"`
	BackoutPlan           string `json:"backout_plan"`
	CommunicationPlan     string `json:"communication_plan"`

	// Risk assessment
	RiskAssessment string `json:"risk_assessment"`
	RiskMitigation string `json:"risk_mitigation"`
	ImpactAnalysis string `json:"impact_analysis"`

	// Assignment and ownership
	RequestedByID     uint   `json:"requested_by_id" gorm:"not null"`
	RequestedBy       *User  `json:"requested_by,omitempty" gorm:"foreignKey:RequestedByID"`
	AssignedToID      *uint  `json:"assigned_to_id"`
	AssignedTo        *User  `json:"assigned_to,omitempty" gorm:"foreignKey:AssignedToID"`
	AssignmentGroupID *uint  `json:"assignment_group_id"`
	AssignmentGroup   *Group `json:"assignment_group,omitempty" gorm:"foreignKey:AssignmentGroupID"`
	ChangeManagerID   *uint  `json:"change_manager_id"`
	ChangeManager     *User  `json:"change_manager,omitempty" gorm:"foreignKey:ChangeManagerID"`

	// Related entities
	RelatedIncidentID *uint     `json:"related_incident_id"`
	RelatedIncident   *Incident `json:"related_incident,omitempty" gorm:"foreignKey:RelatedIncidentID"`
	RelatedProblemID  *uint     `json:"related_problem_id"`
	RelatedProblem    *Problem  `json:"related_problem,omitempty" gorm:"foreignKey:RelatedProblemID"`

	// Configuration items (CMDB)
	ConfigurationItems []ConfigurationItem `json:"configuration_items,omitempty" gorm:"many2many:change_configuration_items;"`

	// Service information
	ServiceID        *uint     `json:"service_id"`
	Service          *Service  `json:"service,omitempty" gorm:"foreignKey:ServiceID"`
	AffectedServices []Service `json:"affected_services,omitempty" gorm:"many2many:change_affected_services;"`

	// Scheduling
	PlannedStartDate  *time.Time `json:"planned_start_date"`
	PlannedEndDate    *time.Time `json:"planned_end_date"`
	ActualStartDate   *time.Time `json:"actual_start_date"`
	ActualEndDate     *time.Time `json:"actual_end_date"`
	MaintenanceWindow string     `json:"maintenance_window"`
	EstimatedDowntime int        `json:"estimated_downtime"` // Minutes
	ActualDowntime    int        `json:"actual_downtime"`    // Minutes

	// Approval process
	RequiresCABApproval bool             `json:"requires_cab_approval" gorm:"default:true"`
	CABMeetingDate      *time.Time       `json:"cab_meeting_date"`
	CABDecision         string           `json:"cab_decision"`
	CABNotes            string           `json:"cab_notes"`
	Approvals           []ChangeApproval `json:"approvals,omitempty" gorm:"foreignKey:ChangeID"`

	// Implementation details
	ImplementedByID      *uint  `json:"implemented_by_id"`
	ImplementedBy        *User  `json:"implemented_by,omitempty" gorm:"foreignKey:ImplementedByID"`
	ImplementationNotes  string `json:"implementation_notes"`
	ImplementationResult string `json:"implementation_result"`

	// Review and closure
	ReviewNotes        string `json:"review_notes"`
	LessonsLearned     string `json:"lessons_learned"`
	SuccessCriteriaMet bool   `json:"success_criteria_met" gorm:"default:false"`
	ClosureCode        string `json:"closure_code"`
	ClosureNotes       string `json:"closure_notes"`

	// Metrics
	EstimatedCost     float64 `json:"estimated_cost"`
	ActualCost        float64 `json:"actual_cost"`
	EstimatedEffort   int     `json:"estimated_effort"` // Hours
	ActualEffort      int     `json:"actual_effort"`    // Hours
	RollbackRequired  bool    `json:"rollback_required" gorm:"default:false"`
	RollbackPerformed bool    `json:"rollback_performed" gorm:"default:false"`

	// Additional fields
	IsEmergency       bool     `json:"is_emergency" gorm:"default:false"`
	IsStandardChange  bool     `json:"is_standard_change" gorm:"default:false"`
	TemplateID        *uint    `json:"template_id"`
	Tags              []string `json:"tags" gorm:"type:text[]"`
	ExternalReference string   `json:"external_reference"`

	// Audit fields
	CreatedAt        time.Time `json:"created_at"`
	UpdatedAt        time.Time `json:"updated_at"`
	CreatedByID      uint      `json:"created_by_id"`
	CreatedBy        *User     `json:"created_by,omitempty" gorm:"foreignKey:CreatedByID"`
	LastModifiedByID *uint     `json:"last_modified_by_id"`
	LastModifiedBy   *User     `json:"last_modified_by,omitempty" gorm:"foreignKey:LastModifiedByID"`
}

Change represents an ITSM change request.

type ChangeApproval

type ChangeApproval struct {
	ID           uint       `json:"id" gorm:"primaryKey"`
	ChangeID     uint       `json:"change_id" gorm:"not null"`
	Change       *Change    `json:"change,omitempty" gorm:"foreignKey:ChangeID"`
	ApproverID   uint       `json:"approver_id" gorm:"not null"`
	Approver     *User      `json:"approver,omitempty" gorm:"foreignKey:ApproverID"`
	ApprovalType string     `json:"approval_type"` // technical, business, security, etc.
	Status       string     `json:"status"`        // pending, approved, rejected, abstained
	Comments     string     `json:"comments"`
	ApprovedAt   *time.Time `json:"approved_at"`
	CreatedAt    time.Time  `json:"created_at"`
	UpdatedAt    time.Time  `json:"updated_at"`
}

ChangeApproval represents an approval for a change.

type ChangeAttachment

type ChangeAttachment struct {
	ID           uint      `json:"id" gorm:"primaryKey"`
	ChangeID     uint      `json:"change_id" gorm:"not null"`
	Change       *Change   `json:"change,omitempty" gorm:"foreignKey:ChangeID"`
	FileName     string    `json:"file_name" gorm:"not null"`
	FilePath     string    `json:"file_path" gorm:"not null"`
	FileSize     int64     `json:"file_size"`
	ContentType  string    `json:"content_type"`
	UploadedByID uint      `json:"uploaded_by_id" gorm:"not null"`
	UploadedBy   *User     `json:"uploaded_by,omitempty" gorm:"foreignKey:UploadedByID"`
	CreatedAt    time.Time `json:"created_at"`
}

ChangeAttachment represents a file attached to a change.

type ChangeComment

type ChangeComment struct {
	ID         uint      `json:"id" gorm:"primaryKey"`
	ChangeID   uint      `json:"change_id" gorm:"not null"`
	Change     *Change   `json:"change,omitempty" gorm:"foreignKey:ChangeID"`
	AuthorID   uint      `json:"author_id" gorm:"not null"`
	Author     *User     `json:"author,omitempty" gorm:"foreignKey:AuthorID"`
	Comment    string    `json:"comment" gorm:"not null"`
	IsPublic   bool      `json:"is_public" gorm:"default:true"`
	IsWorkNote bool      `json:"is_work_note" gorm:"default:false"`
	CreatedAt  time.Time `json:"created_at"`
	UpdatedAt  time.Time `json:"updated_at"`
}

ChangeComment represents a comment on a change.

type ChangeHistory

type ChangeHistory struct {
	ID           uint      `json:"id" gorm:"primaryKey"`
	ChangeID     uint      `json:"change_id" gorm:"not null"`
	Change       *Change   `json:"change,omitempty" gorm:"foreignKey:ChangeID"`
	FieldName    string    `json:"field_name" gorm:"not null"`
	OldValue     string    `json:"old_value"`
	NewValue     string    `json:"new_value"`
	ChangedByID  uint      `json:"changed_by_id" gorm:"not null"`
	ChangedBy    *User     `json:"changed_by,omitempty" gorm:"foreignKey:ChangedByID"`
	ChangeReason string    `json:"change_reason"`
	CreatedAt    time.Time `json:"created_at"`
}

ChangeHistory tracks changes to a change request.

type ChangeImpact

type ChangeImpact string

ChangeImpact represents the impact level of a change.

const (
	ChangeImpactMinor       ChangeImpact = "minor"
	ChangeImpactSignificant ChangeImpact = "significant"
	ChangeImpactMajor       ChangeImpact = "major"
	ChangeImpactExtensive   ChangeImpact = "extensive"
)

type ChangeListRequest

type ChangeListRequest struct {
	Page          int          `json:"page" form:"page"`
	PerPage       int          `json:"per_page" form:"per_page"`
	Status        ChangeStatus `json:"status" form:"status"`
	Type          ChangeType   `json:"type" form:"type"`
	Risk          ChangeRisk   `json:"risk" form:"risk"`
	RequestedByID uint         `json:"requested_by_id" form:"requested_by_id"`
	AssignedToID  uint         `json:"assigned_to_id" form:"assigned_to_id"`
	Search        string       `json:"search" form:"search"`
	SortBy        string       `json:"sort_by" form:"sort_by"`
	SortOrder     string       `json:"sort_order" form:"sort_order"`
	FromDate      *time.Time   `json:"from_date" form:"from_date"`
	ToDate        *time.Time   `json:"to_date" form:"to_date"`
	RequiresCAB   *bool        `json:"requires_cab" form:"requires_cab"`
	IsEmergency   *bool        `json:"is_emergency" form:"is_emergency"`
}

ChangeListRequest represents a request to list changes.

type ChangeListResponse

type ChangeListResponse struct {
	Changes    []*Change `json:"changes"`
	Total      int64     `json:"total"`
	Page       int       `json:"page"`
	PerPage    int       `json:"per_page"`
	TotalPages int       `json:"total_pages"`
}

ChangeListResponse represents a response containing a list of changes.

type ChangePasswordRequest

type ChangePasswordRequest struct {
	OldPassword string `json:"old_password" binding:"required"`
	NewPassword string `json:"new_password" binding:"required,min=8"`
}

type ChangeRisk

type ChangeRisk string

ChangeRisk represents the risk level of a change.

const (
	ChangeRiskLow      ChangeRisk = "low"
	ChangeRiskMedium   ChangeRisk = "medium"
	ChangeRiskHigh     ChangeRisk = "high"
	ChangeRiskCritical ChangeRisk = "critical"
)

type ChangeStatus

type ChangeStatus string

ChangeStatus represents the current status of a change.

const (
	ChangeStatusDraft            ChangeStatus = "draft"
	ChangeStatusSubmitted        ChangeStatus = "submitted"
	ChangeStatusPlanning         ChangeStatus = "planning"
	ChangeStatusAwaitingApproval ChangeStatus = "awaiting_approval"
	ChangeStatusApproved         ChangeStatus = "approved"
	ChangeStatusScheduled        ChangeStatus = "scheduled"
	ChangeStatusImplementing     ChangeStatus = "implementing"
	ChangeStatusReview           ChangeStatus = "review"
	ChangeStatusClosed           ChangeStatus = "closed"
	ChangeStatusCancelled        ChangeStatus = "cancelled"
	ChangeStatusRejected         ChangeStatus = "rejected"
)

type ChangeTask

type ChangeTask struct {
	ID           uint       `json:"id" gorm:"primaryKey"`
	ChangeID     uint       `json:"change_id" gorm:"not null"`
	Change       *Change    `json:"change,omitempty" gorm:"foreignKey:ChangeID"`
	TaskNumber   string     `json:"task_number" gorm:"not null"`
	Title        string     `json:"title" gorm:"not null"`
	Description  string     `json:"description"`
	AssignedToID *uint      `json:"assigned_to_id"`
	AssignedTo   *User      `json:"assigned_to,omitempty" gorm:"foreignKey:AssignedToID"`
	Status       string     `json:"status"` // pending, in_progress, completed, cancelled
	PlannedStart *time.Time `json:"planned_start"`
	PlannedEnd   *time.Time `json:"planned_end"`
	ActualStart  *time.Time `json:"actual_start"`
	ActualEnd    *time.Time `json:"actual_end"`
	Dependencies string     `json:"dependencies"`
	Order        int        `json:"order"`
	CreatedAt    time.Time  `json:"created_at"`
	UpdatedAt    time.Time  `json:"updated_at"`
}

ChangeTask represents a task within a change.

type ChangeType

type ChangeType string

ChangeType represents the type of change.

const (
	ChangeTypeStandard  ChangeType = "standard"  // Pre-approved, low risk
	ChangeTypeNormal    ChangeType = "normal"    // Requires CAB approval
	ChangeTypeEmergency ChangeType = "emergency" // Urgent, expedited approval
	ChangeTypeMajor     ChangeType = "major"     // Significant impact
)

type Condition

type Condition struct {
	ID         int               `json:"id"`
	WorkflowID int               `json:"workflow_id"`
	Field      string            `json:"field"` // Field to check (e.g., "ticket.priority")
	Operator   ConditionOperator `json:"operator"`
	Value      interface{}       `json:"value"`      // Expected value
	LogicalOp  string            `json:"logical_op"` // AND, OR for combining conditions
	GroupID    int               `json:"group_id"`   // For grouping conditions
}

Condition represents a workflow condition.

type ConditionOperator

type ConditionOperator string

ConditionOperator represents logical operators for conditions.

const (
	OperatorEquals         ConditionOperator = "equals"
	OperatorNotEquals      ConditionOperator = "not_equals"
	OperatorContains       ConditionOperator = "contains"
	OperatorNotContains    ConditionOperator = "not_contains"
	OperatorStartsWith     ConditionOperator = "starts_with"
	OperatorEndsWith       ConditionOperator = "ends_with"
	OperatorGreaterThan    ConditionOperator = "greater_than"
	OperatorLessThan       ConditionOperator = "less_than"
	OperatorGreaterOrEqual ConditionOperator = "greater_or_equal"
	OperatorLessOrEqual    ConditionOperator = "less_or_equal"
	OperatorIn             ConditionOperator = "in"
	OperatorNotIn          ConditionOperator = "not_in"
	OperatorIsEmpty        ConditionOperator = "is_empty"
	OperatorIsNotEmpty     ConditionOperator = "is_not_empty"
	OperatorMatchesRegex   ConditionOperator = "matches_regex"
)

type ConfigurationItem

type ConfigurationItem struct {
	ID          uint          `json:"id" gorm:"primaryKey"`
	CINumber    string        `json:"ci_number" gorm:"uniqueIndex;not null"`
	Name        string        `json:"name" gorm:"not null;index"`
	DisplayName string        `json:"display_name"`
	Type        CIType        `json:"type" gorm:"not null;index"`
	SubType     string        `json:"sub_type"`
	Status      CIStatus      `json:"status" gorm:"not null;default:'active';index"`
	Environment CIEnvironment `json:"environment" gorm:"index"`
	Description string        `json:"description"`

	// Classification
	Category        string `json:"category"`
	SubCategory     string `json:"sub_category"`
	Criticality     int    `json:"criticality" gorm:"default:3"` // 1-5 scale
	BusinessService string `json:"business_service"`

	// Ownership and management
	OwnerID        *uint  `json:"owner_id"`
	Owner          *User  `json:"owner,omitempty" gorm:"foreignKey:OwnerID"`
	ManagedByID    *uint  `json:"managed_by_id"`
	ManagedBy      *User  `json:"managed_by,omitempty" gorm:"foreignKey:ManagedByID"`
	SupportGroupID *uint  `json:"support_group_id"`
	SupportGroup   *Group `json:"support_group,omitempty" gorm:"foreignKey:SupportGroupID"`
	Department     string `json:"department"`

	// Location information
	Location     string `json:"location"`
	Building     string `json:"building"`
	Floor        string `json:"floor"`
	Room         string `json:"room"`
	Rack         string `json:"rack"`
	RackPosition string `json:"rack_position"`

	// Technical details
	Manufacturer    string `json:"manufacturer"`
	Model           string `json:"model"`
	SerialNumber    string `json:"serial_number" gorm:"index"`
	AssetTag        string `json:"asset_tag" gorm:"index"`
	Version         string `json:"version"`
	OperatingSystem string `json:"operating_system"`
	IPAddress       string `json:"ip_address"`
	MACAddress      string `json:"mac_address"`
	Hostname        string `json:"hostname"`
	Domain          string `json:"domain"`

	// Hardware specifications
	CPU      string `json:"cpu"`
	CPUCores int    `json:"cpu_cores"`
	RAM      int    `json:"ram"`     // GB
	Storage  int    `json:"storage"` // GB

	// Financial information
	PurchaseDate       *time.Time `json:"purchase_date"`
	PurchasePrice      float64    `json:"purchase_price"`
	Currency           string     `json:"currency"`
	PONumber           string     `json:"po_number"`
	InvoiceNumber      string     `json:"invoice_number"`
	VendorID           *uint      `json:"vendor_id"`
	Vendor             *Vendor    `json:"vendor,omitempty" gorm:"foreignKey:VendorID"`
	WarrantyExpiry     *time.Time `json:"warranty_expiry"`
	LeaseExpiry        *time.Time `json:"lease_expiry"`
	DepreciationMethod string     `json:"depreciation_method"`
	CurrentValue       float64    `json:"current_value"`

	// Lifecycle management
	InstallDate         *time.Time `json:"install_date"`
	CommissionDate      *time.Time `json:"commission_date"`
	DecommissionDate    *time.Time `json:"decommission_date"`
	LastAuditDate       *time.Time `json:"last_audit_date"`
	NextAuditDate       *time.Time `json:"next_audit_date"`
	LastMaintenanceDate *time.Time `json:"last_maintenance_date"`
	NextMaintenanceDate *time.Time `json:"next_maintenance_date"`
	EndOfLife           *time.Time `json:"end_of_life"`

	// Relationships
	ParentCIID   *uint               `json:"parent_ci_id"`
	ParentCI     *ConfigurationItem  `json:"parent_ci,omitempty" gorm:"foreignKey:ParentCIID"`
	ChildCIs     []ConfigurationItem `json:"child_cis,omitempty" gorm:"foreignKey:ParentCIID"`
	RelatedCIs   []ConfigurationItem `json:"related_cis,omitempty" gorm:"many2many:ci_relationships;"`
	Dependencies []ConfigurationItem `json:"dependencies,omitempty" gorm:"many2many:ci_dependencies;"`

	// Compliance and security
	ComplianceStatus   string     `json:"compliance_status"`
	SecurityLevel      string     `json:"security_level"`
	DataClassification string     `json:"data_classification"`
	LastSecurityScan   *time.Time `json:"last_security_scan"`
	ComplianceTags     []string   `json:"compliance_tags" gorm:"type:text[]"`

	// Additional attributes (flexible schema)
	Attributes map[string]interface{} `json:"attributes" gorm:"type:jsonb"`

	// Documentation
	DocumentationURL   string   `json:"documentation_url"`
	ConfigurationNotes string   `json:"configuration_notes"`
	Tags               []string `json:"tags" gorm:"type:text[]"`

	// Audit fields
	CreatedAt        time.Time  `json:"created_at"`
	UpdatedAt        time.Time  `json:"updated_at"`
	CreatedByID      uint       `json:"created_by_id"`
	CreatedBy        *User      `json:"created_by,omitempty" gorm:"foreignKey:CreatedByID"`
	LastModifiedByID *uint      `json:"last_modified_by_id"`
	LastModifiedBy   *User      `json:"last_modified_by,omitempty" gorm:"foreignKey:LastModifiedByID"`
	LastVerifiedAt   *time.Time `json:"last_verified_at"`
	LastVerifiedByID *uint      `json:"last_verified_by_id"`
	LastVerifiedBy   *User      `json:"last_verified_by,omitempty" gorm:"foreignKey:LastVerifiedByID"`
}

ConfigurationItem represents an item in the CMDB.

type ControllerMapping

type ControllerMapping struct {
	Controller string `yaml:"Controller,omitempty" json:"controller,omitempty"`
	Command    string `yaml:"Command,omitempty" json:"command,omitempty"` // GET, POST, etc.
}

ControllerMapping maps invokers to REST endpoints.

type CreateArticleRequest

type CreateArticleRequest struct {
	ArticleTypeID uint                      `json:"article_type_id" binding:"required"`
	SenderTypeID  uint                      `json:"sender_type_id" binding:"required"`
	From          string                    `json:"from"`
	To            string                    `json:"to"`
	CC            string                    `json:"cc"`
	Subject       string                    `json:"subject" binding:"required"`
	Body          string                    `json:"body" binding:"required"`
	ContentType   string                    `json:"content_type"`
	CreateBy      uint                      `json:"-"`
	Attachments   []CreateAttachmentRequest `json:"attachments"`
}

CreateArticleRequest represents a request to create a new article.

type CreateAttachmentRequest

type CreateAttachmentRequest struct {
	Filename    string `json:"filename" binding:"required"`
	ContentSize int    `json:"content_size"`
	ContentType string `json:"content_type"`
	Content     []byte `json:"content" binding:"required"`
}

CreateAttachmentRequest represents a request to create an attachment.

type CreateTicketRequest

type CreateTicketRequest struct {
	Title             string                `json:"title" binding:"required"`
	QueueID           uint                  `json:"queue_id"`
	StateID           uint                  `json:"state_id"`
	PriorityID        uint                  `json:"priority_id"`
	CustomerUserID    uint                  `json:"customer_user_id"`
	CustomerID        string                `json:"customer_id"`
	OwnerID           uint                  `json:"owner_id"`
	ResponsibleUserID uint                  `json:"responsible_user_id"`
	TypeID            uint                  `json:"type_id"`
	TenantID          uint                  `json:"tenant_id" binding:"required"`
	CreateBy          uint                  `json:"-"`
	InitialArticle    *CreateArticleRequest `json:"initial_article"`
}

CreateTicketRequest represents a request to create a new ticket.

type CustomerAccount

type CustomerAccount struct {
	ID             int       `json:"id" db:"id"`
	Username       string    `json:"username" db:"username"`
	Email          string    `json:"email" db:"email"`
	OrganizationID *string   `json:"organization_id,omitempty" db:"organization_id"`
	PasswordHash   *string   `json:"-" db:"password_hash"`
	FullName       *string   `json:"full_name,omitempty" db:"full_name"`
	PhoneNumber    *string   `json:"phone_number,omitempty" db:"phone_number"`
	MobileNumber   *string   `json:"mobile_number,omitempty" db:"mobile_number"`
	IsActive       bool      `json:"is_active" db:"is_active"`
	CreatedAt      time.Time `json:"created_at" db:"created_at"`
	CreatedBy      int       `json:"created_by" db:"created_by"`
	UpdatedAt      time.Time `json:"updated_at" db:"updated_at"`
	UpdatedBy      int       `json:"updated_by" db:"updated_by"`

	// Joined fields
	Organization *Organization `json:"organization,omitempty"`
}

CustomerAccount represents a customer account.

type DBGroupRole

type DBGroupRole struct {
	RoleID          int       `json:"role_id"`
	GroupID         int       `json:"group_id"`
	PermissionKey   string    `json:"permission_key"`
	PermissionValue int       `json:"permission_value"`
	CreateTime      time.Time `json:"create_time"`
	CreateBy        int       `json:"create_by"`
	ChangeTime      time.Time `json:"change_time"`
	ChangeBy        int       `json:"change_by"`
}

Maps to the `group_role` table.

type DBRole

type DBRole struct {
	ID         int       `json:"id"`
	Name       string    `json:"name"`
	Comments   string    `json:"comments"`
	ValidID    int       `json:"valid_id"`
	CreateTime time.Time `json:"create_time"`
	CreateBy   int       `json:"create_by"`
	ChangeTime time.Time `json:"change_time"`
	ChangeBy   int       `json:"change_by"`
}

Maps to the `roles` table.

func (*DBRole) IsValid

func (r *DBRole) IsValid() bool

IsValid returns true if the role is active (valid_id = 1).

type DBRoleUser

type DBRoleUser struct {
	UserID     int       `json:"user_id"`
	RoleID     int       `json:"role_id"`
	CreateTime time.Time `json:"create_time"`
	CreateBy   int       `json:"create_by"`
	ChangeTime time.Time `json:"change_time"`
	ChangeBy   int       `json:"change_by"`
}

Maps to the `role_user` table.

type DayOfWeek

type DayOfWeek int

DayOfWeek represents a day of the week.

const (
	Sunday DayOfWeek = iota
	Monday
	Tuesday
	Wednesday
	Thursday
	Friday
	Saturday
)

type DebuggerConfig

type DebuggerConfig struct {
	DebugThreshold string `yaml:"DebugThreshold,omitempty" json:"debug_threshold,omitempty"` // debug, info, notice, error
	TestMode       string `yaml:"TestMode,omitempty" json:"test_mode,omitempty"`             // 0 or 1
}

DebuggerConfig controls debug logging for the webservice.

type EmailAccount

type EmailAccount struct {
	ID                  int       `json:"id" db:"id"`
	Login               string    `json:"login" db:"login"`
	Host                string    `json:"host" db:"host"`
	AccountType         string    `json:"account_type" db:"account_type"`
	QueueID             int       `json:"queue_id" db:"queue_id"`
	DispatchingMode     string    `json:"dispatching_mode"`
	Trusted             bool      `json:"trusted" db:"trusted"`
	AllowTrustedHeaders bool      `json:"allow_trusted_headers"`
	IMAPFolder          *string   `json:"imap_folder,omitempty" db:"imap_folder"`
	Comments            *string   `json:"comments,omitempty" db:"comments"`
	ValidID             int       `json:"valid_id" db:"valid_id"`
	IsActive            bool      `json:"is_active"`
	PollIntervalSeconds int       `json:"poll_interval_seconds,omitempty"`
	PasswordEncrypted   string    `json:"-" db:"pw"`
	CreatedAt           time.Time `json:"created_at" db:"create_time"`
	CreatedBy           int       `json:"created_by" db:"create_by"`
	UpdatedAt           time.Time `json:"updated_at" db:"change_time"`
	UpdatedBy           int       `json:"updated_by" db:"change_by"`
	Queue               *Queue    `json:"queue,omitempty"`
}

EmailAccount mirrors OTRS's mail_account table plus derived metadata for the inbound poller.

type EmailTemplate

type EmailTemplate struct {
	ID              int       `json:"id" db:"id"`
	TemplateName    string    `json:"template_name" db:"template_name"`
	SubjectTemplate *string   `json:"subject_template,omitempty" db:"subject_template"`
	BodyTemplate    *string   `json:"body_template,omitempty" db:"body_template"`
	TemplateType    *string   `json:"template_type,omitempty" db:"template_type"`
	IsActive        bool      `json:"is_active" db:"is_active"`
	CreatedAt       time.Time `json:"created_at" db:"created_at"`
	CreatedBy       int       `json:"created_by" db:"created_by"`
	UpdatedAt       time.Time `json:"updated_at" db:"updated_at"`
	UpdatedBy       int       `json:"updated_by" db:"updated_by"`
}

EmailTemplate represents an email template for automated responses.

type EscalateTicketRequest

type EscalateTicketRequest struct {
	PriorityID uint   `json:"priority_id" binding:"required"`
	Reason     string `json:"reason" binding:"required"`
}

EscalateTicketRequest represents a request to escalate a ticket.

type EscalationAction

type EscalationAction struct {
	Type   string      `json:"type"` // assign_to_user, assign_to_group, change_priority, notify, etc.
	Config interface{} `json:"config"`
}

EscalationAction defines what happens during escalation.

type EscalationCondition

type EscalationCondition struct {
	Field    string      `json:"field"`    // e.g., "priority", "customer.tier", "ticket.reopen_count"
	Operator string      `json:"operator"` // e.g., "equals", "greater_than", "contains"
	Value    interface{} `json:"value"`
}

EscalationCondition defines conditions for escalation.

type EscalationHistory

type EscalationHistory struct {
	ID               int               `json:"id"`
	TicketID         int               `json:"ticket_id"`
	PolicyID         int               `json:"policy_id"`
	RuleID           int               `json:"rule_id"`
	FromLevel        EscalationLevel   `json:"from_level"`
	ToLevel          EscalationLevel   `json:"to_level"`
	Trigger          EscalationTrigger `json:"trigger"`
	TriggerDetails   string            `json:"trigger_details"`
	PreviousAssignee *int              `json:"previous_assignee,omitempty"`
	NewAssignee      *int              `json:"new_assignee,omitempty"`
	EscalatedBy      *int              `json:"escalated_by,omitempty"` // User who triggered manual escalation
	EscalatedAt      time.Time         `json:"escalated_at"`
	Notes            string            `json:"notes"`
	AutoEscalated    bool              `json:"auto_escalated"`
}

EscalationHistory records escalation events.

type EscalationLevel

type EscalationLevel int

EscalationLevel represents a level in the escalation hierarchy.

const (
	EscalationLevel1 EscalationLevel = 1 // Tier 1 Support
	EscalationLevel2 EscalationLevel = 2 // Tier 2 Support
	EscalationLevel3 EscalationLevel = 3 // Tier 3 Support / Engineering
	EscalationLevel4 EscalationLevel = 4 // Management
	EscalationLevel5 EscalationLevel = 5 // Executive
)

func (EscalationLevel) CanEscalateTo

func (el EscalationLevel) CanEscalateTo(target EscalationLevel) bool

CanEscalateTo checks if escalation to target level is valid.

func (EscalationLevel) GetLevelName

func (el EscalationLevel) GetLevelName() string

GetLevelName returns the name of an escalation level.

func (EscalationLevel) IsHigherThan

func (el EscalationLevel) IsHigherThan(other EscalationLevel) bool

IsHigherThan checks if this level is higher than another.

type EscalationMatrix

type EscalationMatrix struct {
	ID          int                       `json:"id"`
	Name        string                    `json:"name"`
	Description string                    `json:"description"`
	Mappings    []EscalationMatrixMapping `json:"mappings"`
	IsActive    bool                      `json:"is_active"`
	CreatedAt   time.Time                 `json:"created_at"`
	UpdatedAt   time.Time                 `json:"updated_at"`
}

EscalationMatrix defines escalation relationships between teams.

type EscalationMatrixMapping

type EscalationMatrixMapping struct {
	FromTeamID      int    `json:"from_team_id"`
	ToTeamID        int    `json:"to_team_id"`
	EscalationLevel int    `json:"escalation_level"`
	Conditions      string `json:"conditions"` // JSON string of conditions
	AutoApprove     bool   `json:"auto_approve"`
}

EscalationMatrixMapping defines team escalation relationships.

type EscalationMetrics

type EscalationMetrics struct {
	TicketID            int             `json:"ticket_id"`
	TotalEscalations    int             `json:"total_escalations"`
	CurrentLevel        EscalationLevel `json:"current_level"`
	TimeAtLevel1        time.Duration   `json:"time_at_level1"`
	TimeAtLevel2        time.Duration   `json:"time_at_level2"`
	TimeAtLevel3        time.Duration   `json:"time_at_level3"`
	TimeAtLevel4        time.Duration   `json:"time_at_level4"`
	TimeAtLevel5        time.Duration   `json:"time_at_level5"`
	FirstEscalationTime time.Duration   `json:"first_escalation_time"`
	ResolutionAfterEsc  time.Duration   `json:"resolution_after_escalation"`
	EscalationEffective bool            `json:"escalation_effective"` // Was escalation helpful
}

EscalationMetrics tracks escalation performance.

type EscalationNotification

type EscalationNotification struct {
	NotifyCustomer    bool     `json:"notify_customer"`
	NotifyAssignee    bool     `json:"notify_assignee"`
	NotifyManager     bool     `json:"notify_manager"`
	NotifyCustomList  []string `json:"notify_custom_list"` // Email addresses
	CustomerTemplate  int      `json:"customer_template_id"`
	InternalTemplate  int      `json:"internal_template_id"`
	IncludeTicketInfo bool     `json:"include_ticket_info"`
	IncludeHistory    bool     `json:"include_history"`
}

EscalationNotification defines notification settings.

type EscalationPath

type EscalationPath struct {
	ID          int                   `json:"id"`
	Name        string                `json:"name"`
	Description string                `json:"description"`
	QueueID     int                   `json:"queue_id"`
	Levels      []EscalationPathLevel `json:"levels"`
	IsDefault   bool                  `json:"is_default"`
	CreatedAt   time.Time             `json:"created_at"`
	UpdatedAt   time.Time             `json:"updated_at"`
}

EscalationPath represents the escalation hierarchy.

func (*EscalationPath) GetLevelConfig

func (ep *EscalationPath) GetLevelConfig(level EscalationLevel) *EscalationPathLevel

GetLevelConfig returns configuration for a specific level.

func (*EscalationPath) GetNextLevel

func (ep *EscalationPath) GetNextLevel(currentLevel EscalationLevel) *EscalationPathLevel

GetNextLevel returns the next escalation level.

type EscalationPathLevel

type EscalationPathLevel struct {
	Level            EscalationLevel `json:"level"`
	Name             string          `json:"name"`
	AssignToUserID   *int            `json:"assign_to_user_id,omitempty"`
	AssignToGroupID  *int            `json:"assign_to_group_id,omitempty"`
	AssignmentMethod string          `json:"assignment_method"` // specific_user, group_round_robin, skills_based
	ResponseTime     int             `json:"response_time_minutes"`
	ResolutionTime   int             `json:"resolution_time_minutes"`
	NotifyUsers      []int           `json:"notify_users"`
	NotifyGroups     []int           `json:"notify_groups"`
}

EscalationPathLevel defines a level in the escalation path.

type EscalationPolicy

type EscalationPolicy struct {
	ID                int                    `json:"id"`
	Name              string                 `json:"name"`
	Description       string                 `json:"description"`
	Priority          int                    `json:"priority"` // Higher priority policies execute first
	IsActive          bool                   `json:"is_active"`
	ApplyToQueues     []int                  `json:"apply_to_queues"`     // Queue IDs this policy applies to
	ApplyToCategories []string               `json:"apply_to_categories"` // Ticket categories
	Rules             []EscalationRule       `json:"rules"`
	Notifications     EscalationNotification `json:"notifications"`
	CreatedBy         int                    `json:"created_by"`
	CreatedAt         time.Time              `json:"created_at"`
	UpdatedAt         time.Time              `json:"updated_at"`
}

EscalationPolicy defines an escalation policy.

type EscalationRequest

type EscalationRequest struct {
	ID            int             `json:"id"`
	TicketID      int             `json:"ticket_id"`
	RequestedBy   int             `json:"requested_by"`
	RequestedAt   time.Time       `json:"requested_at"`
	TargetLevel   EscalationLevel `json:"target_level"`
	TargetTeamID  *int            `json:"target_team_id,omitempty"`
	TargetUserID  *int            `json:"target_user_id,omitempty"`
	Reason        string          `json:"reason"`
	Priority      string          `json:"priority"`
	Status        string          `json:"status"` // pending, approved, rejected, cancelled
	ApprovedBy    *int            `json:"approved_by,omitempty"`
	ApprovedAt    *time.Time      `json:"approved_at,omitempty"`
	ApprovalNotes string          `json:"approval_notes"`
	ExpiresAt     time.Time       `json:"expires_at"`
}

EscalationRequest represents a request for escalation (for approval workflows).

type EscalationRule

type EscalationRule struct {
	ID             int                   `json:"id"`
	PolicyID       int                   `json:"policy_id"`
	Level          EscalationLevel       `json:"level"`
	Trigger        EscalationTrigger     `json:"trigger"`
	Conditions     []EscalationCondition `json:"conditions"`
	Actions        []EscalationAction    `json:"actions"`
	TimeThreshold  int                   `json:"time_threshold_minutes"` // For time-based triggers
	BusinessHours  bool                  `json:"business_hours_only"`
	AutoEscalate   bool                  `json:"auto_escalate"`    // Automatically escalate without confirmation
	SkipIfAssigned bool                  `json:"skip_if_assigned"` // Skip if ticket already assigned
	Order          int                   `json:"order"`            // Execution order within policy
}

EscalationRule defines a single escalation rule.

func (*EscalationRule) ShouldTrigger

func (er *EscalationRule) ShouldTrigger(context map[string]interface{}) bool

ShouldTrigger evaluates if escalation should trigger based on conditions.

type EscalationTrigger

type EscalationTrigger string

EscalationTrigger represents what triggers an escalation.

const (
	EscalationTriggerSLAWarning  EscalationTrigger = "sla_warning"
	EscalationTriggerSLABreach   EscalationTrigger = "sla_breach"
	EscalationTriggerTimeElapsed EscalationTrigger = "time_elapsed"
	EscalationTriggerPriority    EscalationTrigger = "priority"
	EscalationTriggerCustomerVIP EscalationTrigger = "customer_vip"
	EscalationTriggerKeyword     EscalationTrigger = "keyword"
	EscalationTriggerManual      EscalationTrigger = "manual"
	EscalationTriggerNoResponse  EscalationTrigger = "no_response"
	EscalationTriggerReopenCount EscalationTrigger = "reopen_count"
	EscalationTriggerSentiment   EscalationTrigger = "sentiment"
)

type EventConfig

type EventConfig struct {
	Event        string `yaml:"Event,omitempty" json:"event,omitempty"`
	Asynchronous string `yaml:"Asynchronous,omitempty" json:"asynchronous,omitempty"` // 0 or 1
}

EventConfig defines event triggers for invokers.

type Facet

type Facet struct {
	Value string `json:"value"`
	Count int64  `json:"count"`
}

Facet represents a search facet.

type FormTemplate

type FormTemplate struct {
	ID              uint                   `json:"id" gorm:"primaryKey"`
	Name            string                 `json:"name" gorm:"not null;uniqueIndex"`
	Description     string                 `json:"description"`
	FormSchema      map[string]interface{} `json:"form_schema" gorm:"type:jsonb"`
	ValidationRules map[string]interface{} `json:"validation_rules" gorm:"type:jsonb"`
	IsActive        bool                   `json:"is_active" gorm:"default:true"`
	Version         int                    `json:"version" gorm:"default:1"`
	CreatedAt       time.Time              `json:"created_at"`
	UpdatedAt       time.Time              `json:"updated_at"`
}

FormTemplate represents a form template for service requests.

type GenericAgentActions

type GenericAgentActions struct {
	// contains filtered or unexported fields
}

GenericAgentActions represents actions to apply to matching tickets.

func (*GenericAgentActions) Delete

func (a *GenericAgentActions) Delete() bool

Delete returns true if tickets should be deleted.

func (*GenericAgentActions) DynamicFieldValues

func (a *GenericAgentActions) DynamicFieldValues() map[string]string

DynamicFieldValues returns dynamic field values to set. Keys are field names (without DynamicField_ prefix), values are the values to set.

func (*GenericAgentActions) HasActions

func (a *GenericAgentActions) HasActions() bool

HasActions returns true if any actions are defined.

func (*GenericAgentActions) NewCustomerID

func (a *GenericAgentActions) NewCustomerID() string

NewCustomerID returns the new customer ID to set.

func (*GenericAgentActions) NewCustomerUserLogin

func (a *GenericAgentActions) NewCustomerUserLogin() string

NewCustomerUserLogin returns the new customer user login to set.

func (*GenericAgentActions) NewLockID

func (a *GenericAgentActions) NewLockID() *int

NewLockID returns the new lock ID to set.

func (*GenericAgentActions) NewOwnerID

func (a *GenericAgentActions) NewOwnerID() *int

NewOwnerID returns the new owner user ID to set.

func (*GenericAgentActions) NewPendingTime

func (a *GenericAgentActions) NewPendingTime() *time.Time

NewPendingTime returns the pending time to set.

func (*GenericAgentActions) NewPendingTimeDiff

func (a *GenericAgentActions) NewPendingTimeDiff() int

NewPendingTimeDiff returns pending time offset in minutes.

func (*GenericAgentActions) NewPriorityID

func (a *GenericAgentActions) NewPriorityID() *int

NewPriorityID returns the new priority ID to set.

func (*GenericAgentActions) NewQueueID

func (a *GenericAgentActions) NewQueueID() *int

NewQueueID returns the new queue ID to set.

func (*GenericAgentActions) NewResponsibleID

func (a *GenericAgentActions) NewResponsibleID() *int

NewResponsibleID returns the new responsible user ID to set.

func (*GenericAgentActions) NewSLAID

func (a *GenericAgentActions) NewSLAID() *int

NewSLAID returns the new SLA ID to set.

func (*GenericAgentActions) NewServiceID

func (a *GenericAgentActions) NewServiceID() *int

NewServiceID returns the new service ID to set.

func (*GenericAgentActions) NewStateID

func (a *GenericAgentActions) NewStateID() *int

NewStateID returns the new state ID to set, or nil if not specified.

func (*GenericAgentActions) NewTitle

func (a *GenericAgentActions) NewTitle() string

NewTitle returns the new title to set.

func (*GenericAgentActions) NewTypeID

func (a *GenericAgentActions) NewTypeID() *int

NewTypeID returns the new type ID to set.

func (*GenericAgentActions) NoteBody

func (a *GenericAgentActions) NoteBody() string

NoteBody returns the note body to add.

func (*GenericAgentActions) NoteSubject

func (a *GenericAgentActions) NoteSubject() string

NoteSubject returns the note subject to add.

type GenericAgentJob

type GenericAgentJob struct {
	Name      string            `json:"name"`
	Valid     bool              `json:"valid"`
	Config    map[string]string `json:"config"`
	LastRunAt *time.Time        `json:"last_run_at,omitempty"`
}

GenericAgentJob represents a generic agent job configuration. Jobs are stored as key-value pairs in the database (job_name, job_key, job_value).

func (*GenericAgentJob) Actions

func (j *GenericAgentJob) Actions() *GenericAgentActions

Actions returns the actions to apply from the job config.

func (*GenericAgentJob) MatchCriteria

func (j *GenericAgentJob) MatchCriteria() *GenericAgentMatchCriteria

MatchCriteria returns the ticket search criteria from the job config.

func (*GenericAgentJob) ScheduleDays

func (j *GenericAgentJob) ScheduleDays() []int

ScheduleDays returns the days of week when this job should run (0=Sun, 6=Sat).

func (*GenericAgentJob) ScheduleHours

func (j *GenericAgentJob) ScheduleHours() []int

ScheduleHours returns the hours when this job should run (0-23).

func (*GenericAgentJob) ScheduleLastRun

func (j *GenericAgentJob) ScheduleLastRun() *time.Time

ScheduleLastRun returns the last run time from config.

func (*GenericAgentJob) ScheduleMinutes

func (j *GenericAgentJob) ScheduleMinutes() []int

ScheduleMinutes returns the minutes when this job should run (0-59).

type GenericAgentMatchCriteria

type GenericAgentMatchCriteria struct {
	// contains filtered or unexported fields
}

GenericAgentMatchCriteria represents ticket search criteria.

func (*GenericAgentMatchCriteria) CustomerID

func (c *GenericAgentMatchCriteria) CustomerID() string

CustomerID returns customer ID pattern to match.

func (*GenericAgentMatchCriteria) CustomerUserLogin

func (c *GenericAgentMatchCriteria) CustomerUserLogin() string

CustomerUserLogin returns customer user login to match.

func (*GenericAgentMatchCriteria) HasCriteria

func (c *GenericAgentMatchCriteria) HasCriteria() bool

HasCriteria returns true if any match criteria are defined.

func (*GenericAgentMatchCriteria) LockIDs

func (c *GenericAgentMatchCriteria) LockIDs() []int

LockIDs returns lock IDs to match.

func (*GenericAgentMatchCriteria) OwnerIDs

func (c *GenericAgentMatchCriteria) OwnerIDs() []int

OwnerIDs returns owner user IDs to match.

func (*GenericAgentMatchCriteria) PriorityIDs

func (c *GenericAgentMatchCriteria) PriorityIDs() []int

PriorityIDs returns priority IDs to match.

func (*GenericAgentMatchCriteria) QueueIDs

func (c *GenericAgentMatchCriteria) QueueIDs() []int

QueueIDs returns queue IDs to match.

func (*GenericAgentMatchCriteria) SLAIDs

func (c *GenericAgentMatchCriteria) SLAIDs() []int

SLAIDs returns SLA IDs to match.

func (*GenericAgentMatchCriteria) ServiceIDs

func (c *GenericAgentMatchCriteria) ServiceIDs() []int

ServiceIDs returns service IDs to match.

func (*GenericAgentMatchCriteria) StateIDs

func (c *GenericAgentMatchCriteria) StateIDs() []int

StateIDs returns state IDs to match.

func (*GenericAgentMatchCriteria) TicketChangeTimeNewerMinutes

func (c *GenericAgentMatchCriteria) TicketChangeTimeNewerMinutes() int

TicketChangeTimeNewerMinutes returns the last change recency filter.

func (*GenericAgentMatchCriteria) TicketChangeTimeOlderMinutes

func (c *GenericAgentMatchCriteria) TicketChangeTimeOlderMinutes() int

TicketChangeTimeOlderMinutes returns the last change age filter.

func (*GenericAgentMatchCriteria) TicketCreateTimeNewerMinutes

func (c *GenericAgentMatchCriteria) TicketCreateTimeNewerMinutes() int

TicketCreateTimeNewerMinutes returns the recency filter in minutes.

func (*GenericAgentMatchCriteria) TicketCreateTimeOlderMinutes

func (c *GenericAgentMatchCriteria) TicketCreateTimeOlderMinutes() int

TicketCreateTimeOlderMinutes returns the age filter in minutes.

func (*GenericAgentMatchCriteria) TicketEscalationTimeNewerMinutes

func (c *GenericAgentMatchCriteria) TicketEscalationTimeNewerMinutes() int

TicketEscalationTimeNewerMinutes returns escalation time recency filter.

func (*GenericAgentMatchCriteria) TicketEscalationTimeOlderMinutes

func (c *GenericAgentMatchCriteria) TicketEscalationTimeOlderMinutes() int

TicketEscalationTimeOlderMinutes returns escalation time age filter.

func (*GenericAgentMatchCriteria) TicketPendingTimeNewerMinutes

func (c *GenericAgentMatchCriteria) TicketPendingTimeNewerMinutes() int

TicketPendingTimeNewerMinutes returns pending time recency filter.

func (*GenericAgentMatchCriteria) TicketPendingTimeOlderMinutes

func (c *GenericAgentMatchCriteria) TicketPendingTimeOlderMinutes() int

TicketPendingTimeOlderMinutes returns pending time age filter.

func (*GenericAgentMatchCriteria) Title

func (c *GenericAgentMatchCriteria) Title() string

Title returns title pattern to match.

func (*GenericAgentMatchCriteria) TypeIDs

func (c *GenericAgentMatchCriteria) TypeIDs() []int

TypeIDs returns type IDs to match.

type Group

type Group struct {
	// OTRS-compatible fields (required for database operations)
	ID         interface{} `json:"id"` // Can be int or string depending on context
	Name       string      `json:"name"`
	Comments   string      `json:"comments,omitempty"`
	ValidID    int         `json:"valid_id,omitempty"`
	CreateTime time.Time   `json:"create_time,omitempty"`
	CreateBy   int         `json:"create_by,omitempty"`
	ChangeTime time.Time   `json:"change_time,omitempty"`
	ChangeBy   int         `json:"change_by,omitempty"`

	// Additional fields for LDAP/extended functionality
	Description string            `json:"description,omitempty"`
	Type        string            `json:"type,omitempty"`    // ldap, local, external
	DN          string            `json:"dn,omitempty"`      // LDAP Distinguished Name
	Members     []string          `json:"members,omitempty"` // User IDs
	Permissions []string          `json:"permissions,omitempty"`
	IsActive    bool              `json:"is_active,omitempty"`
	IsSystem    bool              `json:"is_system,omitempty"`
	Metadata    map[string]string `json:"metadata,omitempty"`
	CreatedAt   time.Time         `json:"created_at,omitempty"`
	UpdatedAt   time.Time         `json:"updated_at,omitempty"`
}

Group represents a user group in the system.

type GroupMembership

type GroupMembership struct {
	GroupID string    `json:"group_id"`
	UserID  string    `json:"user_id"`
	Role    string    `json:"role,omitempty"` // member, admin, etc.
	AddedBy string    `json:"added_by,omitempty"`
	AddedAt time.Time `json:"added_at"`
}

GroupMembership represents a user's membership in a group.

type Holiday

type Holiday struct {
	ID           int       `json:"id"`
	ConfigID     int       `json:"config_id"`
	Name         string    `json:"name"`
	Date         time.Time `json:"date"`
	IsRecurring  bool      `json:"is_recurring"`            // Repeats every year
	IsFloating   bool      `json:"is_floating"`             // e.g., "Last Monday of May"
	FloatingRule string    `json:"floating_rule,omitempty"` // Rule for floating holidays
}

Holiday represents a non-working holiday.

type Incident

type Incident struct {
	ID             uint             `json:"id" gorm:"primaryKey"`
	IncidentNumber string           `json:"incident_number" gorm:"uniqueIndex;not null"`
	Title          string           `json:"title" gorm:"not null"`
	Description    string           `json:"description"`
	Status         IncidentStatus   `json:"status" gorm:"not null;default:'new'"`
	Severity       IncidentSeverity `json:"severity" gorm:"not null;default:'medium'"`
	Category       IncidentCategory `json:"category" gorm:"not null;default:'other'"`
	SubCategory    string           `json:"sub_category"`

	// Impact and urgency for priority calculation
	Impact   int `json:"impact" gorm:"default:2"`  // 1-5 scale
	Urgency  int `json:"urgency" gorm:"default:2"` // 1-5 scale
	Priority int `json:"priority"`                 // Calculated from impact and urgency

	// Assignment and ownership
	AssignedToID      *uint  `json:"assigned_to_id"`
	AssignedTo        *User  `json:"assigned_to,omitempty" gorm:"foreignKey:AssignedToID"`
	AssignmentGroupID *uint  `json:"assignment_group_id"`
	AssignmentGroup   *Group `json:"assignment_group,omitempty" gorm:"foreignKey:AssignmentGroupID"`

	// Related entities
	ReportedByID   uint  `json:"reported_by_id" gorm:"not null"`
	ReportedBy     *User `json:"reported_by,omitempty" gorm:"foreignKey:ReportedByID"`
	AffectedUserID *uint `json:"affected_user_id"`
	AffectedUser   *User `json:"affected_user,omitempty" gorm:"foreignKey:AffectedUserID"`

	// Related tickets and problems
	RelatedTicketID *uint    `json:"related_ticket_id"`
	RelatedTicket   *Ticket  `json:"related_ticket,omitempty" gorm:"foreignKey:RelatedTicketID"`
	ProblemID       *uint    `json:"problem_id"`
	Problem         *Problem `json:"problem,omitempty" gorm:"foreignKey:ProblemID"`

	// Configuration items (CMDB)
	ConfigurationItemID *uint              `json:"configuration_item_id"`
	ConfigurationItem   *ConfigurationItem `json:"configuration_item,omitempty" gorm:"foreignKey:ConfigurationItemID"`

	// Service information
	ServiceID     *uint    `json:"service_id"`
	Service       *Service `json:"service,omitempty" gorm:"foreignKey:ServiceID"`
	ServiceImpact string   `json:"service_impact"` // Description of service impact

	// Resolution details
	ResolutionCode     string `json:"resolution_code"`
	ResolutionNotes    string `json:"resolution_notes"`
	RootCause          string `json:"root_cause"`
	WorkaroundProvided bool   `json:"workaround_provided" gorm:"default:false"`
	WorkaroundDetails  string `json:"workaround_details"`

	// Time tracking
	DetectedAt   *time.Time `json:"detected_at"`
	ReportedAt   time.Time  `json:"reported_at" gorm:"not null"`
	AssignedAt   *time.Time `json:"assigned_at"`
	InProgressAt *time.Time `json:"in_progress_at"`
	ResolvedAt   *time.Time `json:"resolved_at"`
	ClosedAt     *time.Time `json:"closed_at"`

	// SLA tracking
	ResponseDue   *time.Time `json:"response_due"`
	ResolutionDue *time.Time `json:"resolution_due"`
	ResponseMet   bool       `json:"response_met" gorm:"default:false"`
	ResolutionMet bool       `json:"resolution_met" gorm:"default:false"`

	// Metrics
	TimeToRespond   *int `json:"time_to_respond"` // Minutes
	TimeToResolve   *int `json:"time_to_resolve"` // Minutes
	ReopenCount     int  `json:"reopen_count" gorm:"default:0"`
	EscalationLevel int  `json:"escalation_level" gorm:"default:0"`

	// Additional fields
	IsKnownError      bool     `json:"is_known_error" gorm:"default:false"`
	IsMajorIncident   bool     `json:"is_major_incident" gorm:"default:false"`
	ExternalTicketRef string   `json:"external_ticket_ref"`
	Tags              []string `json:"tags" gorm:"type:text[]"`

	// Audit fields
	CreatedAt        time.Time `json:"created_at"`
	UpdatedAt        time.Time `json:"updated_at"`
	CreatedByID      uint      `json:"created_by_id"`
	CreatedBy        *User     `json:"created_by,omitempty" gorm:"foreignKey:CreatedByID"`
	LastModifiedByID *uint     `json:"last_modified_by_id"`
	LastModifiedBy   *User     `json:"last_modified_by,omitempty" gorm:"foreignKey:LastModifiedByID"`
}

Incident represents an ITSM incident.

func (*Incident) CalculatePriority

func (i *Incident) CalculatePriority()

CalculatePriority calculates priority based on impact and urgency matrix.

func (*Incident) GetTimeToResolve

func (i *Incident) GetTimeToResolve() int

GetTimeToResolve calculates time to resolve in minutes.

func (*Incident) GetTimeToRespond

func (i *Incident) GetTimeToRespond() int

GetTimeToRespond calculates time to respond in minutes.

type IncidentAttachment

type IncidentAttachment struct {
	ID           uint      `json:"id" gorm:"primaryKey"`
	IncidentID   uint      `json:"incident_id" gorm:"not null"`
	Incident     *Incident `json:"incident,omitempty" gorm:"foreignKey:IncidentID"`
	FileName     string    `json:"file_name" gorm:"not null"`
	FilePath     string    `json:"file_path" gorm:"not null"`
	FileSize     int64     `json:"file_size"`
	ContentType  string    `json:"content_type"`
	UploadedByID uint      `json:"uploaded_by_id" gorm:"not null"`
	UploadedBy   *User     `json:"uploaded_by,omitempty" gorm:"foreignKey:UploadedByID"`
	CreatedAt    time.Time `json:"created_at"`
}

IncidentAttachment represents a file attached to an incident.

type IncidentCategory

type IncidentCategory string

IncidentCategory represents the category of an incident.

const (
	CategoryHardware    IncidentCategory = "hardware"
	CategorySoftware    IncidentCategory = "software"
	CategoryNetwork     IncidentCategory = "network"
	CategorySecurity    IncidentCategory = "security"
	CategoryAccess      IncidentCategory = "access"
	CategoryPerformance IncidentCategory = "performance"
	CategoryOther       IncidentCategory = "other"
)

type IncidentComment

type IncidentComment struct {
	ID         uint      `json:"id" gorm:"primaryKey"`
	IncidentID uint      `json:"incident_id" gorm:"not null"`
	Incident   *Incident `json:"incident,omitempty" gorm:"foreignKey:IncidentID"`
	AuthorID   uint      `json:"author_id" gorm:"not null"`
	Author     *User     `json:"author,omitempty" gorm:"foreignKey:AuthorID"`
	Comment    string    `json:"comment" gorm:"not null"`
	IsPublic   bool      `json:"is_public" gorm:"default:true"`
	IsWorkNote bool      `json:"is_work_note" gorm:"default:false"`
	CreatedAt  time.Time `json:"created_at"`
	UpdatedAt  time.Time `json:"updated_at"`
}

IncidentComment represents a comment on an incident.

type IncidentHistory

type IncidentHistory struct {
	ID           uint      `json:"id" gorm:"primaryKey"`
	IncidentID   uint      `json:"incident_id" gorm:"not null"`
	Incident     *Incident `json:"incident,omitempty" gorm:"foreignKey:IncidentID"`
	FieldName    string    `json:"field_name" gorm:"not null"`
	OldValue     string    `json:"old_value"`
	NewValue     string    `json:"new_value"`
	ChangedByID  uint      `json:"changed_by_id" gorm:"not null"`
	ChangedBy    *User     `json:"changed_by,omitempty" gorm:"foreignKey:ChangedByID"`
	ChangeReason string    `json:"change_reason"`
	CreatedAt    time.Time `json:"created_at"`
}

IncidentHistory tracks changes to an incident.

type IncidentListRequest

type IncidentListRequest struct {
	Page            int              `json:"page" form:"page"`
	PerPage         int              `json:"per_page" form:"per_page"`
	Status          IncidentStatus   `json:"status" form:"status"`
	Severity        IncidentSeverity `json:"severity" form:"severity"`
	Category        IncidentCategory `json:"category" form:"category"`
	AssignedToID    uint             `json:"assigned_to_id" form:"assigned_to_id"`
	ReportedByID    uint             `json:"reported_by_id" form:"reported_by_id"`
	Search          string           `json:"search" form:"search"`
	SortBy          string           `json:"sort_by" form:"sort_by"`
	SortOrder       string           `json:"sort_order" form:"sort_order"`
	IsMajorIncident *bool            `json:"is_major_incident" form:"is_major_incident"`
	FromDate        *time.Time       `json:"from_date" form:"from_date"`
	ToDate          *time.Time       `json:"to_date" form:"to_date"`
}

IncidentListRequest represents a request to list incidents.

type IncidentListResponse

type IncidentListResponse struct {
	Incidents  []*Incident `json:"incidents"`
	Total      int64       `json:"total"`
	Page       int         `json:"page"`
	PerPage    int         `json:"per_page"`
	TotalPages int         `json:"total_pages"`
}

IncidentListResponse represents a response containing a list of incidents.

type IncidentRelation

type IncidentRelation struct {
	ID           uint      `json:"id" gorm:"primaryKey"`
	IncidentID   uint      `json:"incident_id" gorm:"not null"`
	Incident     *Incident `json:"incident,omitempty" gorm:"foreignKey:IncidentID"`
	RelatedID    uint      `json:"related_id" gorm:"not null"`
	Related      *Incident `json:"related,omitempty" gorm:"foreignKey:RelatedID"`
	RelationType string    `json:"relation_type"` // parent, child, related, duplicate
	CreatedAt    time.Time `json:"created_at"`
}

IncidentRelation represents relationships between incidents.

type IncidentSeverity

type IncidentSeverity string

IncidentSeverity represents the severity level of an incident.

const (
	SeverityCritical IncidentSeverity = "critical" // Service completely down
	SeverityHigh     IncidentSeverity = "high"     // Major impact
	SeverityMedium   IncidentSeverity = "medium"   // Moderate impact
	SeverityLow      IncidentSeverity = "low"      // Minor impact
)

type IncidentStatus

type IncidentStatus string

IncidentStatus represents the current status of an incident.

const (
	IncidentStatusNew        IncidentStatus = "new"
	IncidentStatusAssigned   IncidentStatus = "assigned"
	IncidentStatusInProgress IncidentStatus = "in_progress"
	IncidentStatusPending    IncidentStatus = "pending"
	IncidentStatusResolved   IncidentStatus = "resolved"
	IncidentStatusClosed     IncidentStatus = "closed"
)

type IndexStats

type IndexStats struct {
	Name          string    `json:"name"`
	DocumentCount int64     `json:"document_count"`
	StorageSize   int64     `json:"storage_size"`
	LastUpdated   time.Time `json:"last_updated"`
	Status        string    `json:"status"`
}

IndexStats represents search index statistics.

type InternalNote

type InternalNote struct {
	ID          uint       `json:"id"`
	TicketID    uint       `json:"ticket_id" binding:"required"`
	AuthorID    uint       `json:"author_id"`
	AuthorName  string     `json:"author_name"`
	AuthorEmail string     `json:"author_email"`
	Content     string     `json:"content" binding:"required"`
	ContentType string     `json:"content_type"` // text/plain or text/html
	IsInternal  bool       `json:"is_internal"`  // Always true for internal notes
	IsImportant bool       `json:"is_important"` // Flag for important notes
	IsPinned    bool       `json:"is_pinned"`    // Pin to top of note list
	Category    string     `json:"category"`     // Optional categorization
	Tags        []string   `json:"tags"`         // Tags for filtering
	Attachments []string   `json:"attachments"`  // Attachment URLs
	CreatedAt   time.Time  `json:"created_at"`
	UpdatedAt   time.Time  `json:"updated_at"`
	EditedBy    uint       `json:"edited_by,omitempty"`
	EditHistory []NoteEdit `json:"edit_history,omitempty"`

	// Related entities
	MentionedUsers []uint `json:"mentioned_users,omitempty"` // @mentions
	RelatedTickets []uint `json:"related_tickets,omitempty"` // Referenced ticket IDs

	// Visibility control
	VisibleToRoles []string `json:"visible_to_roles,omitempty"` // Role-based visibility
	VisibleToUsers []uint   `json:"visible_to_users,omitempty"` // User-specific visibility
}

InternalNote represents an internal note/comment on a ticket.

type InvokerConfig

type InvokerConfig struct {
	Type            string        `yaml:"Type,omitempty" json:"type,omitempty"`
	Description     string        `yaml:"Description,omitempty" json:"description,omitempty"`
	Events          []EventConfig `yaml:"Events,omitempty" json:"events,omitempty"`
	MappingInbound  MappingConfig `yaml:"MappingInbound,omitempty" json:"mapping_inbound,omitempty"`
	MappingOutbound MappingConfig `yaml:"MappingOutbound,omitempty" json:"mapping_outbound,omitempty"`
}

InvokerConfig defines an outbound invoker.

type KnowledgeArticle

type KnowledgeArticle struct {
	ID            uint              `json:"id" gorm:"primaryKey"`
	ArticleNumber string            `json:"article_number" gorm:"uniqueIndex;not null"`
	Title         string            `json:"title" gorm:"not null;index"`
	Summary       string            `json:"summary"`
	Content       string            `json:"content" gorm:"type:text"`
	Type          ArticleType       `json:"type" gorm:"not null;default:'reference';index"`
	Status        ArticleStatus     `json:"status" gorm:"not null;default:'draft';index"`
	Visibility    ArticleVisibility `json:"visibility" gorm:"not null;default:'internal';index"`

	// Categorization
	CategoryID    uint               `json:"category_id" gorm:"index"`
	Category      *KnowledgeCategory `json:"category,omitempty" gorm:"foreignKey:CategoryID"`
	SubCategoryID *uint              `json:"sub_category_id"`
	SubCategory   *KnowledgeCategory `json:"sub_category,omitempty" gorm:"foreignKey:SubCategoryID"`
	Tags          []string           `json:"tags" gorm:"type:text[]"`
	Keywords      []string           `json:"keywords" gorm:"type:text[]"`

	// Authorship and ownership
	AuthorID uint  `json:"author_id" gorm:"not null"`
	Author   *User `json:"author,omitempty" gorm:"foreignKey:AuthorID"`
	OwnerID  *uint `json:"owner_id"`
	Owner    *User `json:"owner,omitempty" gorm:"foreignKey:OwnerID"`
	ExpertID *uint `json:"expert_id"`
	Expert   *User `json:"expert,omitempty" gorm:"foreignKey:ExpertID"`

	// Review and approval
	ReviewerID    *uint      `json:"reviewer_id"`
	Reviewer      *User      `json:"reviewer,omitempty" gorm:"foreignKey:ReviewerID"`
	ReviewedAt    *time.Time `json:"reviewed_at"`
	ReviewNotes   string     `json:"review_notes"`
	ApproverID    *uint      `json:"approver_id"`
	Approver      *User      `json:"approver,omitempty" gorm:"foreignKey:ApproverID"`
	ApprovedAt    *time.Time `json:"approved_at"`
	ApprovalNotes string     `json:"approval_notes"`

	// Publishing
	PublishedAt   *time.Time `json:"published_at"`
	PublishedByID *uint      `json:"published_by_id"`
	PublishedBy   *User      `json:"published_by,omitempty" gorm:"foreignKey:PublishedByID"`
	ExpiryDate    *time.Time `json:"expiry_date"`
	ReviewDate    *time.Time `json:"review_date"`

	// Versioning
	Version         int               `json:"version" gorm:"default:1"`
	IsCurrent       bool              `json:"is_current" gorm:"default:true"`
	ParentArticleID *uint             `json:"parent_article_id"`
	ParentArticle   *KnowledgeArticle `json:"parent_article,omitempty" gorm:"foreignKey:ParentArticleID"`

	// Related entities
	RelatedIncidents []Incident          `json:"related_incidents,omitempty" gorm:"many2many:article_incidents;"`
	RelatedProblems  []Problem           `json:"related_problems,omitempty" gorm:"many2many:article_problems;"`
	RelatedChanges   []Change            `json:"related_changes,omitempty" gorm:"many2many:article_changes;"`
	RelatedCIs       []ConfigurationItem `json:"related_cis,omitempty" gorm:"many2many:article_cis;"`
	RelatedArticles  []KnowledgeArticle  `json:"related_articles,omitempty" gorm:"many2many:article_relationships;"`

	// Metrics and feedback
	ViewCount       int     `json:"view_count" gorm:"default:0"`
	UseCount        int     `json:"use_count" gorm:"default:0"`
	HelpfulCount    int     `json:"helpful_count" gorm:"default:0"`
	NotHelpfulCount int     `json:"not_helpful_count" gorm:"default:0"`
	Rating          float64 `json:"rating" gorm:"default:0"`
	RatingCount     int     `json:"rating_count" gorm:"default:0"`

	// Search and SEO
	MetaDescription string `json:"meta_description"`
	MetaKeywords    string `json:"meta_keywords"`
	Slug            string `json:"slug" gorm:"uniqueIndex"`
	SearchRank      int    `json:"search_rank" gorm:"default:0"`

	// Attachments and media
	HasAttachments  bool `json:"has_attachments" gorm:"default:false"`
	HasImages       bool `json:"has_images" gorm:"default:false"`
	HasVideos       bool `json:"has_videos" gorm:"default:false"`
	AttachmentCount int  `json:"attachment_count" gorm:"default:0"`

	// Access control
	RestrictedGroups []Group `json:"restricted_groups,omitempty" gorm:"many2many:article_group_access;"`
	RequiresAuth     bool    `json:"requires_auth" gorm:"default:false"`

	// Additional metadata
	Language       string `json:"language" gorm:"default:'en'"`
	ReadingTime    int    `json:"reading_time"` // Minutes
	Complexity     string `json:"complexity"`   // beginner, intermediate, advanced
	TargetAudience string `json:"target_audience"`
	Prerequisites  string `json:"prerequisites"`

	// Audit fields
	CreatedAt        time.Time  `json:"created_at"`
	UpdatedAt        time.Time  `json:"updated_at"`
	LastViewedAt     *time.Time `json:"last_viewed_at"`
	LastModifiedByID *uint      `json:"last_modified_by_id"`
	LastModifiedBy   *User      `json:"last_modified_by,omitempty" gorm:"foreignKey:LastModifiedByID"`
}

KnowledgeArticle represents a knowledge base article.

type KnowledgeArticleAttachment

type KnowledgeArticleAttachment struct {
	ID            uint              `json:"id" gorm:"primaryKey"`
	ArticleID     uint              `json:"article_id" gorm:"not null"`
	Article       *KnowledgeArticle `json:"article,omitempty" gorm:"foreignKey:ArticleID"`
	FileName      string            `json:"file_name" gorm:"not null"`
	FilePath      string            `json:"file_path" gorm:"not null"`
	FileSize      int64             `json:"file_size"`
	ContentType   string            `json:"content_type"`
	Description   string            `json:"description"`
	IsInline      bool              `json:"is_inline" gorm:"default:false"`
	DownloadCount int               `json:"download_count" gorm:"default:0"`
	UploadedByID  uint              `json:"uploaded_by_id" gorm:"not null"`
	UploadedBy    *User             `json:"uploaded_by,omitempty" gorm:"foreignKey:UploadedByID"`
	CreatedAt     time.Time         `json:"created_at"`
}

KnowledgeArticleAttachment represents a file attached to an article.

type KnowledgeCategory

type KnowledgeCategory struct {
	ID           uint                `json:"id" gorm:"primaryKey"`
	Name         string              `json:"name" gorm:"not null;uniqueIndex"`
	DisplayName  string              `json:"display_name"`
	Description  string              `json:"description"`
	Icon         string              `json:"icon"`
	Color        string              `json:"color"`
	ParentID     *uint               `json:"parent_id"`
	Parent       *KnowledgeCategory  `json:"parent,omitempty" gorm:"foreignKey:ParentID"`
	Children     []KnowledgeCategory `json:"children,omitempty" gorm:"foreignKey:ParentID"`
	Order        int                 `json:"order" gorm:"default:0"`
	IsActive     bool                `json:"is_active" gorm:"default:true"`
	ArticleCount int                 `json:"article_count" gorm:"default:0"`
	CreatedAt    time.Time           `json:"created_at"`
	UpdatedAt    time.Time           `json:"updated_at"`
}

KnowledgeCategory represents a category in the knowledge base.

type KnowledgeSearchRequest

type KnowledgeSearchRequest struct {
	Query      string            `json:"query" form:"query"`
	Type       ArticleType       `json:"type" form:"type"`
	Status     ArticleStatus     `json:"status" form:"status"`
	CategoryID uint              `json:"category_id" form:"category_id"`
	AuthorID   uint              `json:"author_id" form:"author_id"`
	Tags       []string          `json:"tags" form:"tags"`
	Visibility ArticleVisibility `json:"visibility" form:"visibility"`
	Language   string            `json:"language" form:"language"`
	Page       int               `json:"page" form:"page"`
	PerPage    int               `json:"per_page" form:"per_page"`
	SortBy     string            `json:"sort_by" form:"sort_by"`
	SortOrder  string            `json:"sort_order" form:"sort_order"`
}

KnowledgeSearchRequest represents a search request for articles.

type KnowledgeSearchResponse

type KnowledgeSearchResponse struct {
	Articles   []*KnowledgeArticle `json:"articles"`
	Total      int64               `json:"total"`
	Page       int                 `json:"page"`
	PerPage    int                 `json:"per_page"`
	TotalPages int                 `json:"total_pages"`
	SearchTime float64             `json:"search_time"` // Milliseconds
}

KnowledgeSearchResponse represents search results.

type LDAPAuthenticationLog

type LDAPAuthenticationLog struct {
	ID           int       `json:"id" db:"id"`
	ConfigID     int       `json:"config_id" db:"config_id"`
	Username     string    `json:"username" db:"username"`
	UserID       *int      `json:"user_id" db:"user_id"`
	Success      bool      `json:"success" db:"success"`
	ErrorMessage string    `json:"error_message" db:"error_message"`
	IPAddress    string    `json:"ip_address" db:"ip_address"`
	UserAgent    string    `json:"user_agent" db:"user_agent"`
	AuthTime     time.Time `json:"auth_time" db:"auth_time"`
	CreatedAt    time.Time `json:"created_at" db:"created_at"`
}

LDAPAuthenticationLog represents LDAP authentication attempts.

type LDAPConfiguration

type LDAPConfiguration struct {
	ID                   int        `json:"id" db:"id"`
	Name                 string     `json:"name" db:"name"`
	Host                 string     `json:"host" db:"host"`
	Port                 int        `json:"port" db:"port"`
	BaseDN               string     `json:"base_dn" db:"base_dn"`
	BindDN               string     `json:"bind_dn" db:"bind_dn"`
	BindPassword         string     `json:"bind_password" db:"bind_password"`
	UserFilter           string     `json:"user_filter" db:"user_filter"`
	UserSearchBase       string     `json:"user_search_base" db:"user_search_base"`
	GroupFilter          string     `json:"group_filter" db:"group_filter"`
	GroupSearchBase      string     `json:"group_search_base" db:"group_search_base"`
	UseTLS               bool       `json:"use_tls" db:"use_tls"`
	StartTLS             bool       `json:"start_tls" db:"start_tls"`
	InsecureSkipVerify   bool       `json:"insecure_skip_verify" db:"insecure_skip_verify"`
	AttributeMapping     string     `json:"attribute_mapping" db:"attribute_mapping"` // JSON
	GroupMemberAttribute string     `json:"group_member_attribute" db:"group_member_attribute"`
	AutoCreateUsers      bool       `json:"auto_create_users" db:"auto_create_users"`
	AutoUpdateUsers      bool       `json:"auto_update_users" db:"auto_update_users"`
	AutoCreateGroups     bool       `json:"auto_create_groups" db:"auto_create_groups"`
	SyncIntervalMinutes  int        `json:"sync_interval_minutes" db:"sync_interval_minutes"`
	DefaultRoleID        int        `json:"default_role_id" db:"default_role_id"`
	AdminGroups          string     `json:"admin_groups" db:"admin_groups"` // JSON array
	UserGroups           string     `json:"user_groups" db:"user_groups"`   // JSON array
	IsActive             bool       `json:"is_active" db:"is_active"`
	TestMode             bool       `json:"test_mode" db:"test_mode"`
	LastSyncAt           *time.Time `json:"last_sync_at" db:"last_sync_at"`
	SyncStatus           string     `json:"sync_status" db:"sync_status"`
	SyncMessage          string     `json:"sync_message" db:"sync_message"`
	CreatedAt            time.Time  `json:"created_at" db:"created_at"`
	UpdatedAt            time.Time  `json:"updated_at" db:"updated_at"`
	CreatedBy            int        `json:"created_by" db:"created_by"`
	UpdatedBy            int        `json:"updated_by" db:"updated_by"`
}

LDAPConfiguration represents LDAP configuration stored in database.

type LDAPConnectionTest

type LDAPConnectionTest struct {
	Success      bool      `json:"success"`
	ErrorMessage string    `json:"error_message,omitempty"`
	ResponseTime int64     `json:"response_time"` // Milliseconds
	ServerInfo   string    `json:"server_info,omitempty"`
	UserCount    int       `json:"user_count,omitempty"`
	GroupCount   int       `json:"group_count,omitempty"`
	TestedAt     time.Time `json:"tested_at"`
}

LDAPConnectionTest represents a test connection result.

type LDAPGroupMapping

type LDAPGroupMapping struct {
	ID             int       `json:"id" db:"id"`
	GroupID        int       `json:"group_id" db:"group_id"`
	ConfigID       int       `json:"config_id" db:"config_id"`
	LDAPGroupDN    string    `json:"ldap_group_dn" db:"ldap_group_dn"`
	LDAPGroupName  string    `json:"ldap_group_name" db:"ldap_group_name"`
	LDAPObjectGUID string    `json:"ldap_object_guid" db:"ldap_object_guid"`
	LDAPObjectSID  string    `json:"ldap_object_sid" db:"ldap_object_sid"`
	RoleMapping    string    `json:"role_mapping" db:"role_mapping"` // JSON
	LastSyncAt     time.Time `json:"last_sync_at" db:"last_sync_at"`
	IsActive       bool      `json:"is_active" db:"is_active"`
	CreatedAt      time.Time `json:"created_at" db:"created_at"`
	UpdatedAt      time.Time `json:"updated_at" db:"updated_at"`
}

LDAPGroupMapping represents mapping between LDAP and GoatFlow groups.

type LDAPSyncHistory

type LDAPSyncHistory struct {
	ID            int        `json:"id" db:"id"`
	ConfigID      int        `json:"config_id" db:"config_id"`
	StartTime     time.Time  `json:"start_time" db:"start_time"`
	EndTime       *time.Time `json:"end_time" db:"end_time"`
	Status        string     `json:"status" db:"status"` // running, completed, failed
	UsersFound    int        `json:"users_found" db:"users_found"`
	UsersCreated  int        `json:"users_created" db:"users_created"`
	UsersUpdated  int        `json:"users_updated" db:"users_updated"`
	UsersDisabled int        `json:"users_disabled" db:"users_disabled"`
	GroupsFound   int        `json:"groups_found" db:"groups_found"`
	GroupsCreated int        `json:"groups_created" db:"groups_created"`
	GroupsUpdated int        `json:"groups_updated" db:"groups_updated"`
	ErrorCount    int        `json:"error_count" db:"error_count"`
	ErrorLog      string     `json:"error_log" db:"error_log"`       // JSON array of errors
	Duration      int64      `json:"duration" db:"duration"`         // Milliseconds
	TriggeredBy   string     `json:"triggered_by" db:"triggered_by"` // manual, scheduled, api
	CreatedAt     time.Time  `json:"created_at" db:"created_at"`
}

LDAPSyncHistory represents LDAP sync history.

type LDAPSyncStatistics

type LDAPSyncStatistics struct {
	ConfigID           int        `json:"config_id"`
	TotalSyncs         int        `json:"total_syncs"`
	SuccessfulSyncs    int        `json:"successful_syncs"`
	FailedSyncs        int        `json:"failed_syncs"`
	LastSyncAt         *time.Time `json:"last_sync_at"`
	LastSuccessfulSync *time.Time `json:"last_successful_sync"`
	AverageDuration    int64      `json:"average_duration"` // Milliseconds
	TotalUsersCreated  int        `json:"total_users_created"`
	TotalUsersUpdated  int        `json:"total_users_updated"`
	TotalGroupsCreated int        `json:"total_groups_created"`
	TotalGroupsUpdated int        `json:"total_groups_updated"`
	ErrorRate          float64    `json:"error_rate"`
}

LDAPSyncStatistics represents aggregated sync statistics.

type LDAPUserMapping

type LDAPUserMapping struct {
	ID             int       `json:"id" db:"id"`
	UserID         int       `json:"user_id" db:"user_id"`
	ConfigID       int       `json:"config_id" db:"config_id"`
	LDAPUserDN     string    `json:"ldap_user_dn" db:"ldap_user_dn"`
	LDAPUsername   string    `json:"ldap_username" db:"ldap_username"`
	LDAPObjectGUID string    `json:"ldap_object_guid" db:"ldap_object_guid"`
	LDAPObjectSID  string    `json:"ldap_object_sid" db:"ldap_object_sid"`
	LDAPAttributes string    `json:"ldap_attributes" db:"ldap_attributes"` // JSON
	LastSyncAt     time.Time `json:"last_sync_at" db:"last_sync_at"`
	IsActive       bool      `json:"is_active" db:"is_active"`
	CreatedAt      time.Time `json:"created_at" db:"created_at"`
	UpdatedAt      time.Time `json:"updated_at" db:"updated_at"`
}

LDAPUserMapping represents mapping between LDAP and GoatFlow users.

type LoginRequest

type LoginRequest struct {
	Email    string `json:"email" binding:"required,email"`
	Password string `json:"password" binding:"required,min=6"`
}

type LoginResponse

type LoginResponse struct {
	Token        string    `json:"token"`
	RefreshToken string    `json:"refresh_token"`
	User         *User     `json:"user"`
	ExpiresAt    time.Time `json:"expires_at"`
}

type LookupItem

type LookupItem struct {
	ID     int    `json:"id"`
	Value  string `json:"value"`
	Label  string `json:"label"`
	Order  int    `json:"order"`
	Active bool   `json:"active"`
}

LookupItem represents a generic lookup value (priority, type, status, etc.)

type MappingConfig

type MappingConfig struct {
	Type   string                 `yaml:"Type,omitempty" json:"type,omitempty"` // Simple, XSLT, etc.
	Config map[string]interface{} `yaml:"Config,omitempty" json:"config,omitempty"`
}

MappingConfig defines data transformation rules.

type MergeHistory

type MergeHistory struct {
	ID             uint      `json:"id"`
	TicketID       uint      `json:"ticket_id"`
	Operation      string    `json:"operation"` // "merge", "unmerge", "split"
	RelatedTickets []uint    `json:"related_tickets"`
	PerformedBy    uint      `json:"performed_by"`
	PerformedAt    time.Time `json:"performed_at"`
	Details        string    `json:"details"`
}

MergeHistory represents the history of merge operations.

type MergeMonthStat

type MergeMonthStat struct {
	Month    string `json:"month"`
	Year     int    `json:"year"`
	Merges   int    `json:"merges"`
	Unmerges int    `json:"unmerges"`
}

MergeMonthStat represents monthly merge statistics.

type MergeReasonStat

type MergeReasonStat struct {
	Reason string `json:"reason"`
	Count  int    `json:"count"`
}

MergeReasonStat represents statistics for a merge reason.

type MergeRequest

type MergeRequest struct {
	ParentTicketID   uint   `json:"parent_ticket_id" binding:"required"`
	ChildTicketIDs   []uint `json:"child_ticket_ids" binding:"required,min=1"`
	Reason           string `json:"reason" binding:"required"`
	Notes            string `json:"notes,omitempty"`
	MergeMessages    bool   `json:"merge_messages"`
	MergeAttachments bool   `json:"merge_attachments"`
	CloseChildren    bool   `json:"close_children"`
}

MergeRequest represents a request to merge tickets.

type MergeStatistics

type MergeStatistics struct {
	TotalMerges       int               `json:"total_merges"`
	ActiveMerges      int               `json:"active_merges"`
	UnmergedCount     int               `json:"unmerged_count"`
	AverageChildCount float64           `json:"average_child_count"`
	TopMergeReasons   []MergeReasonStat `json:"top_merge_reasons"`
	MergesByMonth     []MergeMonthStat  `json:"merges_by_month"`
}

MergeStatistics provides statistics about merge operations.

type MergeTicketsRequest

type MergeTicketsRequest struct {
	TargetTicketID uint `json:"target_ticket_id" binding:"required"`
	SourceTicketID uint `json:"source_ticket_id" binding:"required"`
}

MergeTicketsRequest represents a request to merge tickets.

type MergeValidation

type MergeValidation struct {
	CanMerge    bool     `json:"can_merge"`
	Warnings    []string `json:"warnings,omitempty"`
	Errors      []string `json:"errors,omitempty"`
	Suggestions []string `json:"suggestions,omitempty"`
}

MergeValidation represents validation results for a merge operation.

type NoteActivity

type NoteActivity struct {
	ID           uint      `json:"id"`
	NoteID       uint      `json:"note_id"`
	TicketID     uint      `json:"ticket_id"`
	UserID       uint      `json:"user_id"`
	UserName     string    `json:"user_name"`
	ActivityType string    `json:"activity_type"` // created, edited, deleted, pinned, unpinned
	Details      string    `json:"details"`
	Timestamp    time.Time `json:"timestamp"`
}

NoteActivity represents activity on internal notes.

type NoteCategory

type NoteCategory struct {
	ID          uint   `json:"id"`
	Name        string `json:"name"`
	Description string `json:"description"`
	Color       string `json:"color"` // For UI display
	Icon        string `json:"icon"`  // Icon identifier
	Order       int    `json:"order"`
	Active      bool   `json:"active"`
}

NoteCategory represents categories for organizing notes.

type NoteEdit

type NoteEdit struct {
	ID         uint      `json:"id"`
	NoteID     uint      `json:"note_id"`
	EditorID   uint      `json:"editor_id"`
	EditorName string    `json:"editor_name"`
	OldContent string    `json:"old_content"`
	NewContent string    `json:"new_content"`
	EditedAt   time.Time `json:"edited_at"`
	EditReason string    `json:"edit_reason,omitempty"`
}

NoteEdit represents an edit history entry.

type NoteExport

type NoteExport struct {
	TicketNumber string         `json:"ticket_number"`
	TicketTitle  string         `json:"ticket_title"`
	Notes        []InternalNote `json:"notes"`
	ExportedAt   time.Time      `json:"exported_at"`
	ExportedBy   string         `json:"exported_by"`
	Format       string         `json:"format"` // json, csv, pdf
}

NoteExport represents exported note data.

type NoteFilter

type NoteFilter struct {
	TicketID      uint       `json:"ticket_id,omitempty"`
	AuthorID      uint       `json:"author_id,omitempty"`
	Category      string     `json:"category,omitempty"`
	Tags          []string   `json:"tags,omitempty"`
	IsImportant   *bool      `json:"is_important,omitempty"`
	IsPinned      *bool      `json:"is_pinned,omitempty"`
	DateFrom      *time.Time `json:"date_from,omitempty"`
	DateTo        *time.Time `json:"date_to,omitempty"`
	SearchQuery   string     `json:"search_query,omitempty"`
	IncludeEdited bool       `json:"include_edited,omitempty"`
	Limit         int        `json:"limit,omitempty"`
	Offset        int        `json:"offset,omitempty"`
	SortBy        string     `json:"sort_by,omitempty"`    // created_at, updated_at
	SortOrder     string     `json:"sort_order,omitempty"` // asc, desc
}

NoteFilter for searching/filtering notes.

type NoteMention

type NoteMention struct {
	ID          uint       `json:"id"`
	NoteID      uint       `json:"note_id"`
	MentionedID uint       `json:"mentioned_id"`
	MentionedBy uint       `json:"mentioned_by"`
	MentionType string     `json:"mention_type"` // @user, @team, @role
	IsRead      bool       `json:"is_read"`
	ReadAt      *time.Time `json:"read_at,omitempty"`
	NotifiedAt  *time.Time `json:"notified_at,omitempty"`
}

NoteMention represents a user mention in a note.

type NoteStatistics

type NoteStatistics struct {
	TotalNotes      int            `json:"total_notes"`
	ImportantNotes  int            `json:"important_notes"`
	PinnedNotes     int            `json:"pinned_notes"`
	NotesByAuthor   map[string]int `json:"notes_by_author"`
	NotesByCategory map[string]int `json:"notes_by_category"`
	AverageLength   int            `json:"average_length"`
	LastNoteDate    *time.Time     `json:"last_note_date,omitempty"`
}

NoteStatistics represents statistics about notes.

type NoteTemplate

type NoteTemplate struct {
	ID          uint      `json:"id"`
	Name        string    `json:"name" binding:"required"`
	Content     string    `json:"content" binding:"required"`
	Category    string    `json:"category"`
	Tags        []string  `json:"tags"`
	IsImportant bool      `json:"is_important"`
	Variables   []string  `json:"variables"` // Template variables like {{reason}}
	CreatedBy   uint      `json:"created_by"`
	CreatedAt   time.Time `json:"created_at"`
	UsageCount  int       `json:"usage_count"`
}

NoteTemplate represents a template for quick note creation.

type OperationConfig

type OperationConfig struct {
	Type            string        `yaml:"Type,omitempty" json:"type,omitempty"`
	Description     string        `yaml:"Description,omitempty" json:"description,omitempty"`
	MappingInbound  MappingConfig `yaml:"MappingInbound,omitempty" json:"mapping_inbound,omitempty"`
	MappingOutbound MappingConfig `yaml:"MappingOutbound,omitempty" json:"mapping_outbound,omitempty"`
}

OperationConfig defines an inbound operation.

type Organization

type Organization struct {
	ID            string    `json:"id" db:"id"`
	Name          string    `json:"name" db:"name"`
	AddressLine1  *string   `json:"address_line1,omitempty" db:"address_line1"`
	AddressLine2  *string   `json:"address_line2,omitempty" db:"address_line2"`
	City          *string   `json:"city,omitempty" db:"city"`
	StateProvince *string   `json:"state_province,omitempty" db:"state_province"`
	PostalCode    *string   `json:"postal_code,omitempty" db:"postal_code"`
	Country       *string   `json:"country,omitempty" db:"country"`
	Website       *string   `json:"website,omitempty" db:"website"`
	Notes         *string   `json:"notes,omitempty" db:"notes"`
	IsActive      bool      `json:"is_active" db:"is_active"`
	CreatedAt     time.Time `json:"created_at" db:"created_at"`
	CreatedBy     int       `json:"created_by" db:"created_by"`
	UpdatedAt     time.Time `json:"updated_at" db:"updated_at"`
	UpdatedBy     int       `json:"updated_by" db:"updated_by"`
}

Organization represents a customer organization.

type PendingReminder

type PendingReminder struct {
	TicketID          int       `json:"ticket_id"`
	TicketNumber      string    `json:"ticket_number"`
	Title             string    `json:"title"`
	QueueID           int       `json:"queue_id"`
	QueueName         string    `json:"queue_name"`
	PendingUntil      time.Time `json:"pending_until"`
	ResponsibleUserID *int      `json:"responsible_user_id,omitempty"`
	OwnerUserID       *int      `json:"owner_user_id,omitempty"`
	StateName         string    `json:"state_name"`
}

type Permission

type Permission struct {
	ID          string `json:"id"`
	Name        string `json:"name"`
	Description string `json:"description"`
	Category    string `json:"category"`
	IsSystem    bool   `json:"is_system"`
}

Permission represents a system permission.

type Problem

type Problem struct {
	ID            uint            `json:"id" gorm:"primaryKey"`
	ProblemNumber string          `json:"problem_number" gorm:"uniqueIndex;not null"`
	Title         string          `json:"title" gorm:"not null"`
	Description   string          `json:"description"`
	Status        ProblemStatus   `json:"status" gorm:"not null;default:'new'"`
	Priority      ProblemPriority `json:"priority" gorm:"not null;default:'medium'"`
	Category      string          `json:"category"`
	SubCategory   string          `json:"sub_category"`

	// Impact and urgency
	Impact  int `json:"impact" gorm:"default:2"`  // 1-5 scale
	Urgency int `json:"urgency" gorm:"default:2"` // 1-5 scale

	// Assignment and ownership
	AssignedToID      *uint  `json:"assigned_to_id"`
	AssignedTo        *User  `json:"assigned_to,omitempty" gorm:"foreignKey:AssignedToID"`
	AssignmentGroupID *uint  `json:"assignment_group_id"`
	AssignmentGroup   *Group `json:"assignment_group,omitempty" gorm:"foreignKey:AssignmentGroupID"`

	// Related entities
	ReportedByID uint  `json:"reported_by_id" gorm:"not null"`
	ReportedBy   *User `json:"reported_by,omitempty" gorm:"foreignKey:ReportedByID"`

	// Related incidents
	Incidents     []Incident `json:"incidents,omitempty" gorm:"foreignKey:ProblemID"`
	IncidentCount int        `json:"incident_count" gorm:"default:0"`

	// Configuration items (CMDB)
	ConfigurationItemID *uint              `json:"configuration_item_id"`
	ConfigurationItem   *ConfigurationItem `json:"configuration_item,omitempty" gorm:"foreignKey:ConfigurationItemID"`

	// Service information
	ServiceID     *uint    `json:"service_id"`
	Service       *Service `json:"service,omitempty" gorm:"foreignKey:ServiceID"`
	ServiceImpact string   `json:"service_impact"`

	// Root cause analysis
	RootCause         string `json:"root_cause"`
	RootCauseAnalysis string `json:"root_cause_analysis"`
	IsRootCauseFound  bool   `json:"is_root_cause_found" gorm:"default:false"`

	// Known error database
	IsKnownError        bool   `json:"is_known_error" gorm:"default:false"`
	KnownErrorID        string `json:"known_error_id"`
	KnownErrorArticleID *uint  `json:"known_error_article_id"`
	Workaround          string `json:"workaround"`
	WorkaroundProvided  bool   `json:"workaround_provided" gorm:"default:false"`

	// Resolution details
	ResolutionCode     string `json:"resolution_code"`
	ResolutionNotes    string `json:"resolution_notes"`
	PermanentFix       string `json:"permanent_fix"`
	PreventiveMeasures string `json:"preventive_measures"`

	// Time tracking
	DetectedAt   *time.Time `json:"detected_at"`
	ReportedAt   time.Time  `json:"reported_at" gorm:"not null"`
	AssignedAt   *time.Time `json:"assigned_at"`
	InProgressAt *time.Time `json:"in_progress_at"`
	KnownErrorAt *time.Time `json:"known_error_at"`
	ResolvedAt   *time.Time `json:"resolved_at"`
	ClosedAt     *time.Time `json:"closed_at"`

	// SLA tracking
	ResponseDue   *time.Time `json:"response_due"`
	ResolutionDue *time.Time `json:"resolution_due"`
	ResponseMet   bool       `json:"response_met" gorm:"default:false"`
	ResolutionMet bool       `json:"resolution_met" gorm:"default:false"`

	// Metrics
	TimeToIdentify   *int `json:"time_to_identify"`    // Minutes
	TimeToKnownError *int `json:"time_to_known_error"` // Minutes
	TimeToResolve    *int `json:"time_to_resolve"`     // Minutes
	ReopenCount      int  `json:"reopen_count" gorm:"default:0"`

	// Review and approval
	RequiresReview bool       `json:"requires_review" gorm:"default:false"`
	ReviewedByID   *uint      `json:"reviewed_by_id"`
	ReviewedBy     *User      `json:"reviewed_by,omitempty" gorm:"foreignKey:ReviewedByID"`
	ReviewedAt     *time.Time `json:"reviewed_at"`
	ReviewNotes    string     `json:"review_notes"`

	// Additional fields
	Tags              []string `json:"tags" gorm:"type:text[]"`
	ExternalReference string   `json:"external_reference"`
	EstimatedEffort   int      `json:"estimated_effort"` // Hours
	ActualEffort      int      `json:"actual_effort"`    // Hours

	// Audit fields
	CreatedAt        time.Time `json:"created_at"`
	UpdatedAt        time.Time `json:"updated_at"`
	CreatedByID      uint      `json:"created_by_id"`
	CreatedBy        *User     `json:"created_by,omitempty" gorm:"foreignKey:CreatedByID"`
	LastModifiedByID *uint     `json:"last_modified_by_id"`
	LastModifiedBy   *User     `json:"last_modified_by,omitempty" gorm:"foreignKey:LastModifiedByID"`
}

Problem represents an ITSM problem record.

type ProblemAttachment

type ProblemAttachment struct {
	ID           uint      `json:"id" gorm:"primaryKey"`
	ProblemID    uint      `json:"problem_id" gorm:"not null"`
	Problem      *Problem  `json:"problem,omitempty" gorm:"foreignKey:ProblemID"`
	FileName     string    `json:"file_name" gorm:"not null"`
	FilePath     string    `json:"file_path" gorm:"not null"`
	FileSize     int64     `json:"file_size"`
	ContentType  string    `json:"content_type"`
	UploadedByID uint      `json:"uploaded_by_id" gorm:"not null"`
	UploadedBy   *User     `json:"uploaded_by,omitempty" gorm:"foreignKey:UploadedByID"`
	CreatedAt    time.Time `json:"created_at"`
}

ProblemAttachment represents a file attached to a problem.

type ProblemComment

type ProblemComment struct {
	ID         uint      `json:"id" gorm:"primaryKey"`
	ProblemID  uint      `json:"problem_id" gorm:"not null"`
	Problem    *Problem  `json:"problem,omitempty" gorm:"foreignKey:ProblemID"`
	AuthorID   uint      `json:"author_id" gorm:"not null"`
	Author     *User     `json:"author,omitempty" gorm:"foreignKey:AuthorID"`
	Comment    string    `json:"comment" gorm:"not null"`
	IsPublic   bool      `json:"is_public" gorm:"default:true"`
	IsWorkNote bool      `json:"is_work_note" gorm:"default:false"`
	CreatedAt  time.Time `json:"created_at"`
	UpdatedAt  time.Time `json:"updated_at"`
}

ProblemComment represents a comment on a problem.

type ProblemHistory

type ProblemHistory struct {
	ID           uint      `json:"id" gorm:"primaryKey"`
	ProblemID    uint      `json:"problem_id" gorm:"not null"`
	Problem      *Problem  `json:"problem,omitempty" gorm:"foreignKey:ProblemID"`
	FieldName    string    `json:"field_name" gorm:"not null"`
	OldValue     string    `json:"old_value"`
	NewValue     string    `json:"new_value"`
	ChangedByID  uint      `json:"changed_by_id" gorm:"not null"`
	ChangedBy    *User     `json:"changed_by,omitempty" gorm:"foreignKey:ChangedByID"`
	ChangeReason string    `json:"change_reason"`
	CreatedAt    time.Time `json:"created_at"`
}

ProblemHistory tracks changes to a problem.

type ProblemListRequest

type ProblemListRequest struct {
	Page         int             `json:"page" form:"page"`
	PerPage      int             `json:"per_page" form:"per_page"`
	Status       ProblemStatus   `json:"status" form:"status"`
	Priority     ProblemPriority `json:"priority" form:"priority"`
	Category     string          `json:"category" form:"category"`
	AssignedToID uint            `json:"assigned_to_id" form:"assigned_to_id"`
	ReportedByID uint            `json:"reported_by_id" form:"reported_by_id"`
	IsKnownError *bool           `json:"is_known_error" form:"is_known_error"`
	Search       string          `json:"search" form:"search"`
	SortBy       string          `json:"sort_by" form:"sort_by"`
	SortOrder    string          `json:"sort_order" form:"sort_order"`
	FromDate     *time.Time      `json:"from_date" form:"from_date"`
	ToDate       *time.Time      `json:"to_date" form:"to_date"`
}

ProblemListRequest represents a request to list problems.

type ProblemListResponse

type ProblemListResponse struct {
	Problems   []*Problem `json:"problems"`
	Total      int64      `json:"total"`
	Page       int        `json:"page"`
	PerPage    int        `json:"per_page"`
	TotalPages int        `json:"total_pages"`
}

ProblemListResponse represents a response containing a list of problems.

type ProblemPriority

type ProblemPriority string

ProblemPriority represents the priority of a problem.

const (
	ProblemPriorityCritical ProblemPriority = "critical"
	ProblemPriorityHigh     ProblemPriority = "high"
	ProblemPriorityMedium   ProblemPriority = "medium"
	ProblemPriorityLow      ProblemPriority = "low"
	ProblemPriorityPlanning ProblemPriority = "planning"
)

type ProblemStatus

type ProblemStatus string

ProblemStatus represents the current status of a problem.

const (
	ProblemStatusNew        ProblemStatus = "new"
	ProblemStatusAssigned   ProblemStatus = "assigned"
	ProblemStatusAccepted   ProblemStatus = "accepted"
	ProblemStatusInProgress ProblemStatus = "in_progress"
	ProblemStatusPending    ProblemStatus = "pending"
	ProblemStatusKnownError ProblemStatus = "known_error"
	ProblemStatusResolved   ProblemStatus = "resolved"
	ProblemStatusClosed     ProblemStatus = "closed"
)

type ProviderConfig

type ProviderConfig struct {
	Operation map[string]OperationConfig `yaml:"Operation,omitempty" json:"operation,omitempty"`
	Transport TransportConfig            `yaml:"Transport,omitempty" json:"transport,omitempty"`
}

ProviderConfig defines inbound operations (when this system receives requests).

type ProxyConfig

type ProxyConfig struct {
	UseProxy      string `yaml:"UseProxy,omitempty" json:"use_proxy,omitempty"` // 0 or 1
	ProxyHost     string `yaml:"ProxyHost,omitempty" json:"proxy_host,omitempty"`
	ProxyPort     string `yaml:"ProxyPort,omitempty" json:"proxy_port,omitempty"`
	ProxyUser     string `yaml:"ProxyUser,omitempty" json:"proxy_user,omitempty"`
	ProxyPassword string `yaml:"ProxyPassword,omitempty" json:"proxy_password,omitempty"`
}

ProxyConfig defines HTTP proxy settings.

type QueryStats

type QueryStats struct {
	Query      string  `json:"query"`
	Count      int     `json:"count"`
	AvgResults float64 `json:"avg_results"`
	ClickRate  float64 `json:"click_rate"`
}

QueryStats represents statistics for a specific query.

type Queue

type Queue struct {
	ID              uint      `json:"id" db:"id"`
	Name            string    `json:"name" db:"name"`
	SystemAddressID int       `json:"system_address_id,omitempty" db:"system_address_id"`
	SalutationID    int       `json:"salutation_id,omitempty" db:"salutation_id"`
	SignatureID     int       `json:"signature_id,omitempty" db:"signature_id"`
	GroupID         uint      `json:"group_id" db:"group_id"`
	GroupName       string    `json:"group_name,omitempty" db:"group_name"`
	Comment         string    `json:"comment,omitempty" db:"comments"`
	UnlockTimeout   int       `json:"unlock_timeout" db:"unlock_timeout"`
	FollowUpID      int       `json:"follow_up_id" db:"follow_up_id"`
	FollowUpLock    int       `json:"follow_up_lock" db:"follow_up_lock"`
	ValidID         int       `json:"valid_id" db:"valid_id"`
	CreateTime      time.Time `json:"create_time" db:"create_time"`
	CreateBy        uint      `json:"create_by" db:"create_by"`
	ChangeTime      time.Time `json:"change_time" db:"change_time"`
	ChangeBy        uint      `json:"change_by" db:"change_by"`
}

Queue represents a ticket queue.

type QueueInfo

type QueueInfo struct {
	ID          int    `json:"id"`
	Name        string `json:"name"`
	Description string `json:"description"`
	Active      bool   `json:"active"`
}

QueueInfo represents queue information for dropdowns.

type RefreshTokenRequest

type RefreshTokenRequest struct {
	RefreshToken string `json:"refresh_token" binding:"required"`
}

type RequestApproval

type RequestApproval struct {
	ID         uint            `json:"id" gorm:"primaryKey"`
	RequestID  uint            `json:"request_id" gorm:"not null"`
	Request    *ServiceRequest `json:"request,omitempty" gorm:"foreignKey:RequestID"`
	ApproverID uint            `json:"approver_id" gorm:"not null"`
	Approver   *User           `json:"approver,omitempty" gorm:"foreignKey:ApproverID"`
	Level      int             `json:"level" gorm:"default:1"`
	Status     string          `json:"status"` // pending, approved, rejected
	Comments   string          `json:"comments"`
	ApprovedAt *time.Time      `json:"approved_at"`
	CreatedAt  time.Time       `json:"created_at"`
	UpdatedAt  time.Time       `json:"updated_at"`
}

RequestApproval represents an approval for a service request.

type RequestAttachment

type RequestAttachment struct {
	ID           uint            `json:"id" gorm:"primaryKey"`
	RequestID    uint            `json:"request_id" gorm:"not null"`
	Request      *ServiceRequest `json:"request,omitempty" gorm:"foreignKey:RequestID"`
	FileName     string          `json:"file_name" gorm:"not null"`
	FilePath     string          `json:"file_path" gorm:"not null"`
	FileSize     int64           `json:"file_size"`
	ContentType  string          `json:"content_type"`
	UploadedByID uint            `json:"uploaded_by_id" gorm:"not null"`
	UploadedBy   *User           `json:"uploaded_by,omitempty" gorm:"foreignKey:UploadedByID"`
	CreatedAt    time.Time       `json:"created_at"`
}

RequestAttachment represents a file attached to a service request.

type RequestComment

type RequestComment struct {
	ID         uint            `json:"id" gorm:"primaryKey"`
	RequestID  uint            `json:"request_id" gorm:"not null"`
	Request    *ServiceRequest `json:"request,omitempty" gorm:"foreignKey:RequestID"`
	AuthorID   uint            `json:"author_id" gorm:"not null"`
	Author     *User           `json:"author,omitempty" gorm:"foreignKey:AuthorID"`
	Comment    string          `json:"comment" gorm:"not null"`
	IsPublic   bool            `json:"is_public" gorm:"default:true"`
	IsWorkNote bool            `json:"is_work_note" gorm:"default:false"`
	CreatedAt  time.Time       `json:"created_at"`
	UpdatedAt  time.Time       `json:"updated_at"`
}

RequestComment represents a comment on a service request.

type RequestStatus

type RequestStatus string

RequestStatus represents the status of a service request.

const (
	RequestStatusSubmitted  RequestStatus = "submitted"
	RequestStatusPending    RequestStatus = "pending"
	RequestStatusApproved   RequestStatus = "approved"
	RequestStatusRejected   RequestStatus = "rejected"
	RequestStatusInProgress RequestStatus = "in_progress"
	RequestStatusFulfilled  RequestStatus = "fulfilled"
	RequestStatusCancelled  RequestStatus = "cancelled"
	RequestStatusClosed     RequestStatus = "closed"
)

type RequesterConfig

type RequesterConfig struct {
	Invoker   map[string]InvokerConfig `yaml:"Invoker,omitempty" json:"invoker,omitempty"`
	Transport TransportConfig          `yaml:"Transport,omitempty" json:"transport,omitempty"`
}

RequesterConfig defines outbound invokers (when this system makes requests).

type ResponseVariable

type ResponseVariable struct {
	Name         string   `json:"name"`              // e.g., "{{agent_name}}"
	Description  string   `json:"description"`       // Help text
	Type         string   `json:"type"`              // text, date, number, select
	Options      []string `json:"options,omitempty"` // For select type
	DefaultValue string   `json:"default_value,omitempty"`
	AutoFill     string   `json:"auto_fill,omitempty"` // Auto-fill from context (agent_name, ticket_number, etc.)
}

ResponseVariable represents a placeholder in the canned response.

type Role

type Role struct {
	ID          string            `json:"id"`
	Name        string            `json:"name"`
	Description string            `json:"description"`
	Permissions []string          `json:"permissions"`
	IsSystem    bool              `json:"is_system"`
	IsActive    bool              `json:"is_active"`
	Metadata    map[string]string `json:"metadata,omitempty"`
	CreatedAt   time.Time         `json:"created_at"`
	UpdatedAt   time.Time         `json:"updated_at"`
}

Role represents a user role in the system.

type RouteMapping

type RouteMapping struct {
	Route         string   `yaml:"Route,omitempty" json:"route,omitempty"`
	RequestMethod []string `yaml:"RequestMethod,omitempty" json:"request_method,omitempty"`
}

RouteMapping maps operations to REST routes (for providers).

type SLA

type SLA struct {
	ID                uint       `json:"id"`
	Name              string     `json:"name" binding:"required"`
	Description       string     `json:"description"`
	FirstResponseTime int        `json:"first_response_time"` // minutes
	UpdateTime        int        `json:"update_time"`         // minutes
	SolutionTime      int        `json:"solution_time"`       // minutes
	CalendarName      string     `json:"calendar_name"`
	ValidFrom         time.Time  `json:"valid_from"`
	ValidTo           *time.Time `json:"valid_to,omitempty"`
	IsActive          bool       `json:"is_active"`
	Priority          int        `json:"priority"` // 1-5, higher priority SLAs take precedence
	CreatedAt         time.Time  `json:"created_at"`
	UpdatedAt         time.Time  `json:"updated_at"`

	// Conditions for SLA application
	Conditions SLAConditions `json:"conditions"`

	// Escalation rules
	EscalationRules []SLAEscalationRule `json:"escalation_rules,omitempty"`
}

SLA represents a Service Level Agreement.

type SLAConditions

type SLAConditions struct {
	Queues         []uint   `json:"queues,omitempty"`
	Priorities     []int    `json:"priorities,omitempty"`
	Types          []string `json:"types,omitempty"`
	CustomerGroups []uint   `json:"customer_groups,omitempty"`
	Services       []uint   `json:"services,omitempty"`
	Tags           []string `json:"tags,omitempty"`
}

SLAConditions defines when an SLA applies.

type SLAConfiguration

type SLAConfiguration struct {
	EnableSLA               bool   `json:"enable_sla"`
	DefaultCalendarID       uint   `json:"default_calendar_id"`
	AutoAssignSLA           bool   `json:"auto_assign_sla"`
	NotifyOnBreach          bool   `json:"notify_on_breach"`
	NotifyBeforeBreach      bool   `json:"notify_before_breach"`
	NotifyMinutesBefore     int    `json:"notify_minutes_before"`
	PauseOnCustomerReply    bool   `json:"pause_on_customer_reply"`
	PauseOnPendingStatus    bool   `json:"pause_on_pending_status"`
	ExcludeWeekends         bool   `json:"exclude_weekends"`
	ExcludeHolidays         bool   `json:"exclude_holidays"`
	BreachNotificationEmail string `json:"breach_notification_email"`
}

SLAConfiguration represents global SLA settings.

type SLAEscalationHistory

type SLAEscalationHistory struct {
	ID               uint      `json:"id"`
	TicketSLAID      uint      `json:"ticket_sla_id"`
	EscalationRuleID uint      `json:"escalation_rule_id"`
	EscalatedAt      time.Time `json:"escalated_at"`
	NotifiedUsers    []uint    `json:"notified_users"`
	Actions          string    `json:"actions"` // JSON of actions taken
	Success          bool      `json:"success"`
	ErrorMessage     string    `json:"error_message,omitempty"`
}

SLAEscalationHistory tracks escalation events.

type SLAEscalationRule

type SLAEscalationRule struct {
	ID             uint     `json:"id"`
	SLAID          uint     `json:"sla_id"`
	Name           string   `json:"name"`
	TriggerPercent int      `json:"trigger_percent"` // Percentage of time elapsed (e.g., 80%)
	NotifyAgents   []uint   `json:"notify_agents,omitempty"`
	NotifyManagers bool     `json:"notify_managers"`
	AutoAssignTo   *uint    `json:"auto_assign_to,omitempty"`
	ChangePriority *int     `json:"change_priority,omitempty"`
	AddTags        []string `json:"add_tags,omitempty"`
	EmailTemplate  string   `json:"email_template,omitempty"`
	IsActive       bool     `json:"is_active"`
}

SLAEscalationRule defines escalation actions when SLA is breached.

type SLAHoliday

type SLAHoliday struct {
	ID          uint      `json:"id"`
	CalendarID  uint      `json:"calendar_id"`
	Name        string    `json:"name"`
	Date        time.Time `json:"date"`
	IsRecurring bool      `json:"is_recurring"`
}

SLAHoliday represents a non-working day.

type SLAMetrics

type SLAMetrics struct {
	SLAID              uint    `json:"sla_id"`
	SLAName            string  `json:"sla_name"`
	Period             string  `json:"period"`
	TotalTickets       int     `json:"total_tickets"`
	MetCount           int     `json:"met_count"`
	BreachedCount      int     `json:"breached_count"`
	PendingCount       int     `json:"pending_count"`
	CompliancePercent  float64 `json:"compliance_percent"`
	AvgResponseTime    int     `json:"avg_response_time_minutes"`
	AvgSolutionTime    int     `json:"avg_solution_time_minutes"`
	WorstBreachMinutes int     `json:"worst_breach_minutes"`
	TotalEscalations   int     `json:"total_escalations"`
}

SLAMetrics provides SLA performance metrics.

type SLAPauseReason

type SLAPauseReason struct {
	ID          uint       `json:"id"`
	TicketSLAID uint       `json:"ticket_sla_id"`
	Reason      string     `json:"reason" binding:"required"`
	PausedBy    uint       `json:"paused_by"`
	PausedAt    time.Time  `json:"paused_at"`
	ResumedAt   *time.Time `json:"resumed_at,omitempty"`
	Duration    int        `json:"duration_minutes"`
}

SLAPauseReason represents why an SLA was paused.

type SLAReport

type SLAReport struct {
	StartDate         time.Time      `json:"start_date"`
	EndDate           time.Time      `json:"end_date"`
	OverallCompliance float64        `json:"overall_compliance"`
	TotalTickets      int            `json:"total_tickets"`
	TotalBreaches     int            `json:"total_breaches"`
	Metrics           []SLAMetrics   `json:"metrics"`
	TrendData         []SLATrend     `json:"trend_data"`
	TopBreachReasons  []BreachReason `json:"top_breach_reasons"`
}

SLAReport represents a comprehensive SLA report.

type SLATrend

type SLATrend struct {
	Date              time.Time `json:"date"`
	CompliancePercent float64   `json:"compliance_percent"`
	TicketCount       int       `json:"ticket_count"`
	BreachCount       int       `json:"breach_count"`
}

SLATrend represents SLA compliance trend over time.

type SSLConfig

type SSLConfig struct {
	SSLVerifyHostname string `yaml:"SSLVerifyHostname,omitempty" json:"ssl_verify_hostname,omitempty"` // 0 or 1
	SSLVerifyCert     string `yaml:"SSLVerifyCert,omitempty" json:"ssl_verify_cert,omitempty"`         // 0 or 1
	SSLCAFile         string `yaml:"SSLCAFile,omitempty" json:"ssl_ca_file,omitempty"`
	SSLCADir          string `yaml:"SSLCADir,omitempty" json:"ssl_ca_dir,omitempty"`
	SSLCertFile       string `yaml:"SSLCertFile,omitempty" json:"ssl_cert_file,omitempty"`
	SSLKeyFile        string `yaml:"SSLKeyFile,omitempty" json:"ssl_key_file,omitempty"`
}

SSLConfig defines SSL/TLS settings.

type SavedSearch

type SavedSearch struct {
	ID          uint         `json:"id"`
	UserID      uint         `json:"user_id"`
	Name        string       `json:"name" binding:"required"`
	Description string       `json:"description"`
	Filter      SearchFilter `json:"filter"`
	IsPublic    bool         `json:"is_public"`
	IsDefault   bool         `json:"is_default"`
	UsageCount  int          `json:"usage_count"`
	CreatedAt   time.Time    `json:"created_at"`
	UpdatedAt   time.Time    `json:"updated_at"`
}

SavedSearch represents a saved search query.

type ScheduledJob

type ScheduledJob struct {
	Name           string
	Slug           string
	Handler        string
	Schedule       string
	TimeoutSeconds int
	Config         map[string]any
	RunOnStartup   bool // If true, execute immediately when scheduler starts
	LastRunAt      *time.Time
	NextRunAt      *time.Time
	LastStatus     string
	ErrorMessage   *string
	LastDurationMS int64
}

ScheduledJob represents an in-memory background job definition.

func (*ScheduledJob) Clone

func (j *ScheduledJob) Clone() *ScheduledJob

Clone returns a deep copy of the job so schedule mutations stay isolated.

type ScopeDefinition

type ScopeDefinition struct {
	Scope       string `json:"scope"`
	Description string `json:"description"`
	Category    string `json:"category"`     // e.g., "core", "plugin:myplugin"
	RequireRole string `json:"require_role"` // e.g., "Admin", "Agent", "" (any)
	AgentOnly   bool   `json:"agent_only"`   // If true, not available to customers
}

ScopeDefinition defines an API token scope

func GetAllScopes

func GetAllScopes() []*ScopeDefinition

GetAllScopes returns all registered scopes (for admin/debugging)

func GetAvailableScopes

func GetAvailableScopes(userRole string, isCustomer bool) []*ScopeDefinition

GetAvailableScopes returns scopes available for a given user context

type ScopeRegistry

type ScopeRegistry struct {
	// contains filtered or unexported fields
}

ScopeRegistry manages available API token scopes

type SearchAnalytics

type SearchAnalytics struct {
	TotalSearches     int64          `json:"total_searches"`
	UniqueUsers       int            `json:"unique_users"`
	AverageResultSize float64        `json:"average_result_size"`
	TopQueries        []QueryStats   `json:"top_queries"`
	TopFilters        map[string]int `json:"top_filters"`
	SearchTrends      []TrendPoint   `json:"search_trends"`
	ZeroResultQueries []string       `json:"zero_result_queries"`
}

SearchAnalytics represents search usage analytics.

type SearchFilter

type SearchFilter struct {
	// Text search
	Query          string   `json:"query,omitempty"`
	MustContain    []string `json:"must_contain,omitempty"`
	MustNotContain []string `json:"must_not_contain,omitempty"`

	// Field-specific filters
	Statuses   []string `json:"statuses,omitempty"`
	Priorities []string `json:"priorities,omitempty"`
	Queues     []string `json:"queues,omitempty"`
	Agents     []string `json:"agents,omitempty"`
	Customers  []string `json:"customers,omitempty"`
	Tags       []string `json:"tags,omitempty"`

	// Date ranges
	CreatedAfter   *time.Time `json:"created_after,omitempty"`
	CreatedBefore  *time.Time `json:"created_before,omitempty"`
	UpdatedAfter   *time.Time `json:"updated_after,omitempty"`
	UpdatedBefore  *time.Time `json:"updated_before,omitempty"`
	ResolvedAfter  *time.Time `json:"resolved_after,omitempty"`
	ResolvedBefore *time.Time `json:"resolved_before,omitempty"`

	// Numeric filters
	MinResponseTime int `json:"min_response_time,omitempty"`
	MaxResponseTime int `json:"max_response_time,omitempty"`
	MinMessages     int `json:"min_messages,omitempty"`
	MaxMessages     int `json:"max_messages,omitempty"`

	// Special filters
	HasAttachments   *bool `json:"has_attachments,omitempty"`
	HasInternalNotes *bool `json:"has_internal_notes,omitempty"`
	IsEscalated      *bool `json:"is_escalated,omitempty"`
	IsOverdue        *bool `json:"is_overdue,omitempty"`
}

SearchFilter represents advanced search filters.

type SearchHistory

type SearchHistory struct {
	ID         uint         `json:"id"`
	UserID     uint         `json:"user_id"`
	Query      string       `json:"query"`
	Filter     SearchFilter `json:"filter"`
	Results    int          `json:"results"`
	SearchedAt time.Time    `json:"searched_at"`
}

SearchHistory represents a user's search history.

type SearchHit

type SearchHit struct {
	ID         string                 `json:"id"`
	Type       string                 `json:"type"`
	Score      float64                `json:"score"`
	Source     map[string]interface{} `json:"source"`
	Highlights map[string][]string    `json:"highlights,omitempty"`
	Timestamp  time.Time              `json:"timestamp"`
}

SearchHit represents a single search result.

type SearchRequest

type SearchRequest struct {
	Query     string            `json:"query" binding:"required"`
	Type      string            `json:"type,omitempty"` // tickets, notes, customers
	Filters   map[string]string `json:"filters,omitempty"`
	DateFrom  *time.Time        `json:"date_from,omitempty"`
	DateTo    *time.Time        `json:"date_to,omitempty"`
	Page      int               `json:"page,omitempty"`
	PageSize  int               `json:"page_size,omitempty"`
	SortBy    string            `json:"sort_by,omitempty"`
	SortOrder string            `json:"sort_order,omitempty"`
	Highlight bool              `json:"highlight,omitempty"`
	Facets    []string          `json:"facets,omitempty"`
}

SearchRequest represents a search query.

type SearchResult

type SearchResult struct {
	Query       string             `json:"query"`
	TotalHits   int64              `json:"total_hits"`
	Page        int                `json:"page"`
	PageSize    int                `json:"page_size"`
	TotalPages  int                `json:"total_pages"`
	Took        int64              `json:"took_ms"`
	Hits        []SearchHit        `json:"hits"`
	Facets      map[string][]Facet `json:"facets,omitempty"`
	Suggestions []string           `json:"suggestions,omitempty"`
}

SearchResult represents search results.

type SearchSuggestion

type SearchSuggestion struct {
	Text      string  `json:"text"`
	Score     float64 `json:"score"`
	Frequency int     `json:"frequency"`
	Type      string  `json:"type"` // query, field, value
}

SearchSuggestion represents a search suggestion.

type Service

type Service struct {
	ID          uint   `json:"id" gorm:"primaryKey"`
	ServiceCode string `json:"service_code" gorm:"uniqueIndex;not null"`
	Name        string `json:"name" gorm:"not null"`
	DisplayName string `json:"display_name"`
	Description string `json:"description"`
	Type        string `json:"type"`                         // business, technical, infrastructure
	Status      string `json:"status"`                       // active, inactive, deprecated
	Criticality int    `json:"criticality" gorm:"default:3"` // 1-5 scale

	// Ownership
	OwnerID          *uint  `json:"owner_id"`
	Owner            *User  `json:"owner,omitempty" gorm:"foreignKey:OwnerID"`
	ServiceManagerID *uint  `json:"service_manager_id"`
	ServiceManager   *User  `json:"service_manager,omitempty" gorm:"foreignKey:ServiceManagerID"`
	SupportGroupID   *uint  `json:"support_group_id"`
	SupportGroup     *Group `json:"support_group,omitempty" gorm:"foreignKey:SupportGroupID"`

	// Service level
	ServiceLevel       string  `json:"service_level"` // gold, silver, bronze
	SLADocument        string  `json:"sla_document"`
	AvailabilityTarget float64 `json:"availability_target"` // Percentage
	RPO                int     `json:"rpo"`                 // Recovery Point Objective in minutes
	RTO                int     `json:"rto"`                 // Recovery Time Objective in minutes

	// Dependencies
	DependentCIs      []ConfigurationItem `json:"dependent_cis,omitempty" gorm:"many2many:service_ci_dependencies;"`
	DependentServices []Service           `json:"dependent_services,omitempty" gorm:"many2many:service_dependencies;"`

	// Business information
	BusinessUnit  string  `json:"business_unit"`
	CostCenter    string  `json:"cost_center"`
	MonthlyCost   float64 `json:"monthly_cost"`
	AnnualRevenue float64 `json:"annual_revenue"`
	UserCount     int     `json:"user_count"`

	// Documentation
	DocumentationURL     string `json:"documentation_url"`
	RunbookURL           string `json:"runbook_url"`
	DisasterRecoveryPlan string `json:"disaster_recovery_plan"`

	// Audit fields
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

Service represents a business or IT service.

type ServiceCatalogItem

type ServiceCatalogItem struct {
	ID               uint              `json:"id" gorm:"primaryKey"`
	ItemNumber       string            `json:"item_number" gorm:"uniqueIndex;not null"`
	Name             string            `json:"name" gorm:"not null;index"`
	DisplayName      string            `json:"display_name"`
	Description      string            `json:"description"`
	ShortDescription string            `json:"short_description"`
	Type             ServiceItemType   `json:"type" gorm:"not null;default:'request';index"`
	Status           ServiceItemStatus `json:"status" gorm:"not null;default:'active';index"`

	// Categorization
	CategoryID    uint             `json:"category_id" gorm:"index"`
	Category      *ServiceCategory `json:"category,omitempty" gorm:"foreignKey:CategoryID"`
	SubCategoryID *uint            `json:"sub_category_id"`
	SubCategory   *ServiceCategory `json:"sub_category,omitempty" gorm:"foreignKey:SubCategoryID"`
	Tags          []string         `json:"tags" gorm:"type:text[]"`
	Keywords      []string         `json:"keywords" gorm:"type:text[]"`

	// Display and ordering
	Icon       string `json:"icon"`
	Image      string `json:"image"`
	Color      string `json:"color"`
	Order      int    `json:"order" gorm:"default:0"`
	IsFeatured bool   `json:"is_featured" gorm:"default:false"`
	IsPopular  bool   `json:"is_popular" gorm:"default:false"`

	// Fulfillment details
	FulfillmentGroupID *uint   `json:"fulfillment_group_id"`
	FulfillmentGroup   *Group  `json:"fulfillment_group,omitempty" gorm:"foreignKey:FulfillmentGroupID"`
	EstimatedTime      int     `json:"estimated_time"` // Hours
	EstimatedCost      float64 `json:"estimated_cost"`
	RequiresApproval   bool    `json:"requires_approval" gorm:"default:false"`
	ApprovalLevels     int     `json:"approval_levels" gorm:"default:0"`
	AutoAssign         bool    `json:"auto_assign" gorm:"default:false"`

	// SLA and priority
	DefaultPriority   int `json:"default_priority" gorm:"default:3"`
	SLAResponseTime   int `json:"sla_response_time"`   // Minutes
	SLAResolutionTime int `json:"sla_resolution_time"` // Minutes

	// Form and workflow
	FormTemplateID    *uint         `json:"form_template_id"`
	FormTemplate      *FormTemplate `json:"form_template,omitempty" gorm:"foreignKey:FormTemplateID"`
	WorkflowID        *uint         `json:"workflow_id"`
	FulfillmentScript string        `json:"fulfillment_script"`

	// Access control
	AvailableToAll   bool    `json:"available_to_all" gorm:"default:true"`
	RestrictedGroups []Group `json:"restricted_groups,omitempty" gorm:"many2many:catalog_item_group_access;"`
	RestrictedRoles  []Role  `json:"restricted_roles,omitempty" gorm:"many2many:catalog_item_role_access;"`
	RequiresAuth     bool    `json:"requires_auth" gorm:"default:true"`

	// Related items
	RelatedItems  []ServiceCatalogItem `json:"related_items,omitempty" gorm:"many2many:catalog_item_relationships;"`
	Prerequisites []ServiceCatalogItem `json:"prerequisites,omitempty" gorm:"many2many:catalog_item_prerequisites;"`
	IncludedItems []ServiceCatalogItem `json:"included_items,omitempty" gorm:"many2many:catalog_item_inclusions;"`

	// Knowledge base
	KnowledgeArticles  []KnowledgeArticle `json:"knowledge_articles,omitempty" gorm:"many2many:catalog_item_articles;"`
	Instructions       string             `json:"instructions"`
	TermsAndConditions string             `json:"terms_and_conditions"`

	// Metrics
	RequestCount           int     `json:"request_count" gorm:"default:0"`
	FulfillmentRate        float64 `json:"fulfillment_rate" gorm:"default:0"`
	AverageRating          float64 `json:"average_rating" gorm:"default:0"`
	RatingCount            int     `json:"rating_count" gorm:"default:0"`
	AverageFulfillmentTime int     `json:"average_fulfillment_time"` // Minutes

	// Audit fields
	CreatedAt        time.Time `json:"created_at"`
	UpdatedAt        time.Time `json:"updated_at"`
	CreatedByID      uint      `json:"created_by_id"`
	CreatedBy        *User     `json:"created_by,omitempty" gorm:"foreignKey:CreatedByID"`
	LastModifiedByID *uint     `json:"last_modified_by_id"`
	LastModifiedBy   *User     `json:"last_modified_by,omitempty" gorm:"foreignKey:LastModifiedByID"`
}

ServiceCatalogItem represents an item in the service catalog.

type ServiceCatalogListRequest

type ServiceCatalogListRequest struct {
	Page         int               `json:"page" form:"page"`
	PerPage      int               `json:"per_page" form:"per_page"`
	Type         ServiceItemType   `json:"type" form:"type"`
	Status       ServiceItemStatus `json:"status" form:"status"`
	CategoryID   uint              `json:"category_id" form:"category_id"`
	Search       string            `json:"search" form:"search"`
	Tags         []string          `json:"tags" form:"tags"`
	OnlyFeatured bool              `json:"only_featured" form:"only_featured"`
	OnlyPopular  bool              `json:"only_popular" form:"only_popular"`
	SortBy       string            `json:"sort_by" form:"sort_by"`
	SortOrder    string            `json:"sort_order" form:"sort_order"`
}

ServiceCatalogListRequest represents a request to list catalog items.

type ServiceCatalogListResponse

type ServiceCatalogListResponse struct {
	Items      []*ServiceCatalogItem `json:"items"`
	Total      int64                 `json:"total"`
	Page       int                   `json:"page"`
	PerPage    int                   `json:"per_page"`
	TotalPages int                   `json:"total_pages"`
}

ServiceCatalogListResponse represents a response containing catalog items.

type ServiceCategory

type ServiceCategory struct {
	ID          uint              `json:"id" gorm:"primaryKey"`
	Name        string            `json:"name" gorm:"not null;uniqueIndex"`
	DisplayName string            `json:"display_name"`
	Description string            `json:"description"`
	Icon        string            `json:"icon"`
	Image       string            `json:"image"`
	Color       string            `json:"color"`
	ParentID    *uint             `json:"parent_id"`
	Parent      *ServiceCategory  `json:"parent,omitempty" gorm:"foreignKey:ParentID"`
	Children    []ServiceCategory `json:"children,omitempty" gorm:"foreignKey:ParentID"`
	Order       int               `json:"order" gorm:"default:0"`
	IsActive    bool              `json:"is_active" gorm:"default:true"`
	ItemCount   int               `json:"item_count" gorm:"default:0"`
	CreatedAt   time.Time         `json:"created_at"`
	UpdatedAt   time.Time         `json:"updated_at"`
}

ServiceCategory represents a category in the service catalog.

type ServiceItemStatus

type ServiceItemStatus string

ServiceItemStatus represents the status of a service catalog item.

const (
	ServiceItemStatusActive   ServiceItemStatus = "active"
	ServiceItemStatusInactive ServiceItemStatus = "inactive"
	ServiceItemStatusDraft    ServiceItemStatus = "draft"
	ServiceItemStatusRetired  ServiceItemStatus = "retired"
)

type ServiceItemType

type ServiceItemType string

ServiceItemType represents the type of service catalog item.

const (
	ServiceItemTypeService  ServiceItemType = "service"
	ServiceItemTypeRequest  ServiceItemType = "request"
	ServiceItemTypeIncident ServiceItemType = "incident"
	ServiceItemTypeQuestion ServiceItemType = "question"
)

type ServiceRequest

type ServiceRequest struct {
	ID            uint                `json:"id" gorm:"primaryKey"`
	RequestNumber string              `json:"request_number" gorm:"uniqueIndex;not null"`
	CatalogItemID uint                `json:"catalog_item_id" gorm:"not null"`
	CatalogItem   *ServiceCatalogItem `json:"catalog_item,omitempty" gorm:"foreignKey:CatalogItemID"`
	Status        RequestStatus       `json:"status" gorm:"not null;default:'submitted';index"`
	Priority      int                 `json:"priority" gorm:"default:3"`

	// Requester information
	RequesterID    uint   `json:"requester_id" gorm:"not null"`
	Requester      *User  `json:"requester,omitempty" gorm:"foreignKey:RequesterID"`
	RequestedForID *uint  `json:"requested_for_id"`
	RequestedFor   *User  `json:"requested_for,omitempty" gorm:"foreignKey:RequestedForID"`
	Department     string `json:"department"`
	Location       string `json:"location"`

	// Request details
	Title                 string                 `json:"title"`
	Description           string                 `json:"description"`
	BusinessJustification string                 `json:"business_justification"`
	FormData              map[string]interface{} `json:"form_data" gorm:"type:jsonb"`

	// Assignment and fulfillment
	AssignedToID      *uint  `json:"assigned_to_id"`
	AssignedTo        *User  `json:"assigned_to,omitempty" gorm:"foreignKey:AssignedToID"`
	AssignmentGroupID *uint  `json:"assignment_group_id"`
	AssignmentGroup   *Group `json:"assignment_group,omitempty" gorm:"foreignKey:AssignmentGroupID"`
	FulfillmentNotes  string `json:"fulfillment_notes"`

	// Related entities
	RelatedTicketID   *uint     `json:"related_ticket_id"`
	RelatedTicket     *Ticket   `json:"related_ticket,omitempty" gorm:"foreignKey:RelatedTicketID"`
	RelatedIncidentID *uint     `json:"related_incident_id"`
	RelatedIncident   *Incident `json:"related_incident,omitempty" gorm:"foreignKey:RelatedIncidentID"`
	RelatedChangeID   *uint     `json:"related_change_id"`
	RelatedChange     *Change   `json:"related_change,omitempty" gorm:"foreignKey:RelatedChangeID"`

	// Approval process
	ApprovalStatus string            `json:"approval_status"` // pending, approved, rejected
	Approvals      []RequestApproval `json:"approvals,omitempty" gorm:"foreignKey:RequestID"`

	// Time tracking
	SubmittedAt  time.Time  `json:"submitted_at" gorm:"not null"`
	AssignedAt   *time.Time `json:"assigned_at"`
	InProgressAt *time.Time `json:"in_progress_at"`
	FulfilledAt  *time.Time `json:"fulfilled_at"`
	ClosedAt     *time.Time `json:"closed_at"`

	// SLA tracking
	ResponseDue    *time.Time `json:"response_due"`
	FulfillmentDue *time.Time `json:"fulfillment_due"`
	ResponseMet    bool       `json:"response_met" gorm:"default:false"`
	FulfillmentMet bool       `json:"fulfillment_met" gorm:"default:false"`

	// Cost and effort
	EstimatedCost   float64 `json:"estimated_cost"`
	ActualCost      float64 `json:"actual_cost"`
	EstimatedEffort int     `json:"estimated_effort"` // Hours
	ActualEffort    int     `json:"actual_effort"`    // Hours

	// Feedback
	SatisfactionRating *int   `json:"satisfaction_rating"` // 1-5 scale
	Feedback           string `json:"feedback"`

	// Audit fields
	CreatedAt   time.Time `json:"created_at"`
	UpdatedAt   time.Time `json:"updated_at"`
	CreatedByID uint      `json:"created_by_id"`
	CreatedBy   *User     `json:"created_by,omitempty" gorm:"foreignKey:CreatedByID"`
}

ServiceRequest represents a user's service request.

type ServiceRequestListRequest

type ServiceRequestListRequest struct {
	Page          int           `json:"page" form:"page"`
	PerPage       int           `json:"per_page" form:"per_page"`
	Status        RequestStatus `json:"status" form:"status"`
	RequesterID   uint          `json:"requester_id" form:"requester_id"`
	AssignedToID  uint          `json:"assigned_to_id" form:"assigned_to_id"`
	CatalogItemID uint          `json:"catalog_item_id" form:"catalog_item_id"`
	Search        string        `json:"search" form:"search"`
	SortBy        string        `json:"sort_by" form:"sort_by"`
	SortOrder     string        `json:"sort_order" form:"sort_order"`
	FromDate      *time.Time    `json:"from_date" form:"from_date"`
	ToDate        *time.Time    `json:"to_date" form:"to_date"`
}

ServiceRequestListRequest represents a request to list service requests.

type ServiceRequestListResponse

type ServiceRequestListResponse struct {
	Requests   []*ServiceRequest `json:"requests"`
	Total      int64             `json:"total"`
	Page       int               `json:"page"`
	PerPage    int               `json:"per_page"`
	TotalPages int               `json:"total_pages"`
}

ServiceRequestListResponse represents a response containing service requests.

type Session

type Session struct {
	SessionID    string    `json:"session_id"`
	UserID       int       `json:"user_id"`
	UserLogin    string    `json:"user_login"`
	UserType     string    `json:"user_type"` // "User" (agent) or "Customer"
	UserTitle    string    `json:"user_title"`
	UserFullName string    `json:"user_full_name"`
	CreateTime   time.Time `json:"create_time"`
	LastRequest  time.Time `json:"last_request"`
	RemoteAddr   string    `json:"remote_addr"`
	UserAgent    string    `json:"user_agent"`
}

Session represents an active user session. The OTRS sessions table uses a key-value store format with columns: session_id, data_key, data_value, serialized

type SessionData

type SessionData struct {
	SessionID  string `json:"session_id"`
	DataKey    string `json:"data_key"`
	DataValue  string `json:"data_value"`
	Serialized int    `json:"serialized"` // 0=plain text, 1=serialized
}

SessionData represents a key-value pair in the sessions table.

type SimpleTicket

type SimpleTicket struct {
	ID            uint      `json:"id"`
	TicketNumber  string    `json:"ticket_number"`
	Subject       string    `json:"subject"`
	QueueID       uint      `json:"queue_id"`
	TypeID        uint      `json:"type_id"`
	Priority      string    `json:"priority"` // "low", "normal", "high", "urgent"
	Status        string    `json:"status"`   // "new", "open", "pending", "closed"
	CustomerEmail string    `json:"customer_email"`
	CustomerName  string    `json:"customer_name"`
	AssignedTo    uint      `json:"assigned_to"`
	CreatedBy     uint      `json:"created_by"`
	CreatedAt     time.Time `json:"created_at"`
	UpdatedAt     time.Time `json:"updated_at"`
}

It maps to the OTRS-compatible Ticket model but with more intuitive field names.

func FromORTSTicket

func FromORTSTicket(t *Ticket) *SimpleTicket

FromORTSTicket creates a SimpleTicket from OTRS Ticket model.

func (*SimpleTicket) ToORTSTicket

func (st *SimpleTicket) ToORTSTicket() *Ticket

ToORTSTicket converts SimpleTicket to OTRS-compatible Ticket model.

type SplitCriteria

type SplitCriteria struct {
	ByCustomer   bool     `json:"by_customer"`
	ByTimeGap    bool     `json:"by_time_gap"`
	TimeGapHours int      `json:"time_gap_hours,omitempty"`
	BySubject    bool     `json:"by_subject"`
	ByKeywords   []string `json:"by_keywords,omitempty"`
}

SplitCriteria defines criteria for automatic ticket splitting.

type SplitRequest

type SplitRequest struct {
	SourceTicketID  uint          `json:"source_ticket_id" binding:"required"`
	MessageIDs      []uint        `json:"message_ids" binding:"required,min=1"`
	NewTicketTitle  string        `json:"new_ticket_title" binding:"required"`
	NewTicketQueue  uint          `json:"new_ticket_queue" binding:"required"`
	CopyAttachments bool          `json:"copy_attachments"`
	LinkTickets     bool          `json:"link_tickets"`
	SplitCriteria   SplitCriteria `json:"split_criteria,omitempty"`
}

SplitRequest represents a request to split a ticket.

type SplitResult

type SplitResult struct {
	Success           bool   `json:"success"`
	NewTicketID       uint   `json:"new_ticket_id,omitempty"`
	NewTicketNumber   string `json:"new_ticket_number,omitempty"`
	MovedMessages     int    `json:"moved_messages"`
	CopiedAttachments int    `json:"copied_attachments"`
	Error             string `json:"error,omitempty"`
}

SplitResult represents the result of a split operation.

type SystemMaintenance

type SystemMaintenance struct {
	ID               int       `json:"id"`
	StartDate        int64     `json:"start_date"`         // Unix epoch timestamp
	StopDate         int64     `json:"stop_date"`          // Unix epoch timestamp
	Comments         string    `json:"comments"`           // Admin reference/description
	LoginMessage     *string   `json:"login_message"`      // Message shown on login page
	ShowLoginMessage int       `json:"show_login_message"` // 0 or 1
	NotifyMessage    *string   `json:"notify_message"`     // Notification banner message
	ValidID          int       `json:"valid_id"`           // 1=valid, 2=invalid
	CreateTime       time.Time `json:"create_time"`
	CreateBy         int       `json:"create_by"`
	ChangeTime       time.Time `json:"change_time"`
	ChangeBy         int       `json:"change_by"`
}

SystemMaintenance represents a scheduled system maintenance window. This maps directly to the OTRS system_maintenance table.

func (*SystemMaintenance) Duration

func (m *SystemMaintenance) Duration() int

Duration returns the maintenance duration in minutes.

func (*SystemMaintenance) GetLoginMessage

func (m *SystemMaintenance) GetLoginMessage() string

GetLoginMessage returns the login message or empty string if nil.

func (*SystemMaintenance) GetNotifyMessage

func (m *SystemMaintenance) GetNotifyMessage() string

GetNotifyMessage returns the notify message or empty string if nil.

func (*SystemMaintenance) IsCurrentlyActive

func (m *SystemMaintenance) IsCurrentlyActive() bool

IsCurrentlyActive returns true if the maintenance is currently active.

func (*SystemMaintenance) IsPast

func (m *SystemMaintenance) IsPast() bool

IsPast returns true if the maintenance window has ended.

func (*SystemMaintenance) IsUpcoming

func (m *SystemMaintenance) IsUpcoming(withinMinutes int) bool

IsUpcoming returns true if the maintenance starts within the given minutes.

func (*SystemMaintenance) IsValid

func (m *SystemMaintenance) IsValid() bool

IsValid returns true if the maintenance record is valid.

func (*SystemMaintenance) ShowsLoginMessage

func (m *SystemMaintenance) ShowsLoginMessage() bool

ShowsLoginMessage returns true if the login message should be displayed.

func (*SystemMaintenance) StartDateFormatted

func (m *SystemMaintenance) StartDateFormatted() string

StartDateFormatted returns the start date as a formatted string for display.

func (*SystemMaintenance) StartDateInput

func (m *SystemMaintenance) StartDateInput() string

StartDateInput returns the start date formatted for HTML datetime-local input.

func (*SystemMaintenance) StopDateFormatted

func (m *SystemMaintenance) StopDateFormatted() string

StopDateFormatted returns the stop date as a formatted string for display.

func (*SystemMaintenance) StopDateInput

func (m *SystemMaintenance) StopDateInput() string

StopDateInput returns the stop date formatted for HTML datetime-local input.

type TemplateApplication

type TemplateApplication struct {
	TemplateID      uint              `json:"template_id" binding:"required"`
	Variables       map[string]string `json:"variables"`
	CustomerEmail   string            `json:"customer_email" binding:"required,email"`
	CustomerName    string            `json:"customer_name"`
	AdditionalNotes string            `json:"additional_notes,omitempty"`
}

ApplyTemplate creates a new ticket from a template with variable substitution.

type TemplateCategory

type TemplateCategory struct {
	ID          int    `json:"id"`
	Name        string `json:"name"`
	Description string `json:"description"`
	Icon        string `json:"icon,omitempty"` // Icon class for UI
	Order       int    `json:"order"`
	Active      bool   `json:"active"`
}

TemplateCategory represents a category for organizing templates.

type TemplateVariable

type TemplateVariable struct {
	Name         string `json:"name"`        // e.g., "{{customer_name}}"
	Description  string `json:"description"` // Help text for the variable
	Required     bool   `json:"required"`
	DefaultValue string `json:"default_value,omitempty"`
}

TemplateVariable represents a placeholder in the template.

type Ticket

type Ticket struct {
	ID                     int       `json:"id" db:"id"`
	TicketNumber           string    `json:"tn" db:"tn"` // Ticket Number (tn field for compatibility)
	Title                  string    `json:"title" db:"title"`
	QueueID                int       `json:"queue_id" db:"queue_id"`
	TicketLockID           int       `json:"ticket_lock_id" db:"ticket_lock_id"` // 1=unlock, 2=lock, 3=tmp_lock
	TypeID                 *int      `json:"type_id,omitempty" db:"type_id"`
	ServiceID              *int      `json:"service_id,omitempty" db:"service_id"`
	SLAID                  *int      `json:"sla_id,omitempty" db:"sla_id"`
	UserID                 *int      `json:"user_id,omitempty" db:"user_id"` // Owner
	ResponsibleUserID      *int      `json:"responsible_user_id,omitempty" db:"responsible_user_id"`
	CustomerID             *string   `json:"customer_id,omitempty" db:"customer_id"`
	CustomerUserID         *string   `json:"customer_user_id,omitempty" db:"customer_user_id"`
	TicketStateID          int       `json:"ticket_state_id" db:"ticket_state_id"`
	TicketPriorityID       int       `json:"ticket_priority_id" db:"ticket_priority_id"`
	Timeout                int       `json:"timeout,omitempty" db:"timeout"`
	UntilTime              int       `json:"until_time" db:"until_time"`
	EscalationTime         int       `json:"escalation_time" db:"escalation_time"`
	EscalationUpdateTime   int       `json:"escalation_update_time" db:"escalation_update_time"`
	EscalationResponseTime int       `json:"escalation_response_time" db:"escalation_response_time"`
	EscalationSolutionTime int       `json:"escalation_solution_time" db:"escalation_solution_time"`
	ArchiveFlag            int       `json:"archive_flag" db:"archive_flag"` // 0=not archived, 1=archived
	CreateTime             time.Time `json:"create_time" db:"create_time"`
	CreateBy               int       `json:"create_by" db:"create_by"`
	ChangeTime             time.Time `json:"change_time" db:"change_time"`
	ChangeBy               int       `json:"change_by" db:"change_by"`

	// Joined fields (populated when needed)
	Queue           *Queue          `json:"queue,omitempty"`
	State           *TicketState    `json:"state,omitempty"`
	Priority        *TicketPriority `json:"priority,omitempty"`
	Owner           *User           `json:"owner,omitempty"`
	Customer        *User           `json:"customer,omitempty"`
	ResponsibleUser *User           `json:"responsible_user,omitempty"`
}

Ticket represents a support ticket.

func ScanTicket

func ScanTicket(rows *sql.Rows) (*Ticket, error)

ScanTicket is a helper to scan a ticket row from the database.

func (*Ticket) CanBeEditedBy

func (t *Ticket) CanBeEditedBy(userID int, role string) bool

CanBeEditedBy checks if a user can edit this ticket.

func (*Ticket) IsArchived

func (t *Ticket) IsArchived() bool

IsArchived returns true if the ticket is archived.

func (*Ticket) IsClosed

func (t *Ticket) IsClosed() bool

IsClosed returns true if the ticket is in a closed state.

func (*Ticket) IsLocked

func (t *Ticket) IsLocked() bool

IsLocked returns true if the ticket is locked.

type TicketAttributeRelation

type TicketAttributeRelation struct {
	ID         int64     `json:"id" db:"id"`
	Filename   string    `json:"filename" db:"filename"`
	Attribute1 string    `json:"attribute_1" db:"attribute_1"` // e.g., "Queue", "DynamicField_Category"
	Attribute2 string    `json:"attribute_2" db:"attribute_2"` // e.g., "DynamicField_Priority"
	ACLData    string    `json:"acl_data" db:"acl_data"`       // Raw CSV content or base64-encoded Excel
	Priority   int64     `json:"priority" db:"priority"`
	CreateTime time.Time `json:"create_time" db:"create_time"`
	CreateBy   int64     `json:"create_by" db:"create_by"`
	ChangeTime time.Time `json:"change_time" db:"change_time"`
	ChangeBy   int64     `json:"change_by" db:"change_by"`

	// Parsed data (not stored in DB, computed from ACLData)
	Data []AttributeRelationPair `json:"data,omitempty"`
}

TicketAttributeRelation represents a relationship between two ticket attributes. When a value is selected for Attribute1, it restricts the possible values for Attribute2. Data is imported from CSV or Excel files with two columns mapping attr1 values to attr2 values.

func (*TicketAttributeRelation) GetAllowedValues

func (r *TicketAttributeRelation) GetAllowedValues(attr1Value string) []string

GetAllowedValues returns all Attribute2 values that are allowed when Attribute1 has the given value.

func (*TicketAttributeRelation) GetUniqueAttribute1Values

func (r *TicketAttributeRelation) GetUniqueAttribute1Values() []string

GetUniqueAttribute1Values returns all unique values for Attribute1 in the relation data.

func (*TicketAttributeRelation) GetUniqueAttribute2Values

func (r *TicketAttributeRelation) GetUniqueAttribute2Values() []string

GetUniqueAttribute2Values returns all unique values for Attribute2 in the relation data.

type TicketCategory

type TicketCategory struct {
	ID               int       `json:"id" db:"id"`
	Name             string    `json:"name" db:"name"`
	Description      *string   `json:"description,omitempty" db:"description"`
	ParentCategoryID *int      `json:"parent_category_id,omitempty" db:"parent_category_id"`
	IsActive         bool      `json:"is_active" db:"is_active"`
	CreatedAt        time.Time `json:"created_at" db:"created_at"`
	CreatedBy        int       `json:"created_by" db:"created_by"`
	UpdatedAt        time.Time `json:"updated_at" db:"updated_at"`
	UpdatedBy        int       `json:"updated_by" db:"updated_by"`

	// Joined fields
	ParentCategory *TicketCategory   `json:"parent_category,omitempty"`
	SubCategories  []*TicketCategory `json:"sub_categories,omitempty"`
}

TicketCategory represents a category for ticket classification.

type TicketCreateRequest

type TicketCreateRequest struct {
	Title          string   `json:"title" binding:"required,min=1,max=255"`
	QueueID        uint     `json:"queue_id" binding:"required"`
	PriorityID     uint     `json:"priority_id" binding:"required"`
	StateID        uint     `json:"state_id,omitempty"`
	CustomerID     *uint    `json:"customer_id,omitempty"`
	CustomerUserID *string  `json:"customer_user_id,omitempty"`
	Body           string   `json:"body" binding:"required"`
	BodyType       string   `json:"body_type,omitempty"` // defaults to text/plain
	Subject        string   `json:"subject,omitempty"`
	Attachments    []string `json:"attachments,omitempty"` // Base64 encoded files
}

TicketCreateRequest represents a request to create a new ticket.

type TicketFormData

type TicketFormData struct {
	Queues     []QueueInfo  `json:"queues"`
	Priorities []LookupItem `json:"priorities"`
	Types      []LookupItem `json:"types"`
	Statuses   []LookupItem `json:"statuses"`
}

TicketFormData contains all the data needed for ticket forms.

type TicketHistory

type TicketHistory struct {
	ID         uint      `json:"id"`
	TicketID   uint      `json:"ticket_id"`
	ArticleID  *uint     `json:"article_id,omitempty"`
	Name       string    `json:"name"`
	Value      string    `json:"value"`
	CreateTime time.Time `json:"create_time"`
	CreateBy   uint      `json:"create_by"`
	ChangeTime time.Time `json:"change_time"`
	ChangeBy   uint      `json:"change_by"`
}

TicketHistory represents a ticket history entry.

type TicketHistoryEntry

type TicketHistoryEntry struct {
	ID              uint
	HistoryType     string
	Name            string
	CreatorLogin    string
	CreatorFullName string
	CreatedAt       time.Time
	ArticleSubject  string
	QueueName       string
	StateName       string
	PriorityName    string
}

TicketHistoryEntry represents a single history change for a ticket.

type TicketHistoryInsert

type TicketHistoryInsert struct {
	TicketID    int
	ArticleID   *int
	TypeID      int
	QueueID     int
	OwnerID     int
	PriorityID  int
	StateID     int
	CreatedBy   int
	HistoryType string
	Name        string
	CreatedAt   time.Time
}

TicketHistoryInsert captures the data required to persist a history entry.

type TicketLink struct {
	RelatedTicketID    uint
	RelatedTicketTN    string
	RelatedTicketTitle string
	LinkType           string
	LinkState          string
	Direction          string
	CreatorLogin       string
	CreatorFullName    string
	CreatedAt          time.Time
}

TicketLink represents a linked ticket relationship.

type TicketListRequest

type TicketListRequest struct {
	Page                int     `json:"page,omitempty" form:"page"`
	PerPage             int     `json:"per_page,omitempty" form:"per_page"`
	QueueID             *uint   `json:"queue_id,omitempty" form:"queue_id"`
	StateID             *uint   `json:"state_id,omitempty" form:"state_id"`
	PriorityID          *uint   `json:"priority_id,omitempty" form:"priority_id"`
	CustomerID          *uint   `json:"customer_id,omitempty" form:"customer_id"`
	OwnerID             *uint   `json:"owner_id,omitempty" form:"owner_id"`
	Search              string  `json:"search,omitempty" form:"search"`
	SortBy              string  `json:"sort_by,omitempty" form:"sort_by"`
	SortOrder           string  `json:"sort_order,omitempty" form:"sort_order"`
	ArchiveFlag         *int    `json:"archive_flag,omitempty" form:"archive_flag"`
	StartDate           *string `json:"start_date,omitempty" form:"start_date"`
	EndDate             *string `json:"end_date,omitempty" form:"end_date"`
	ExcludeClosedStates bool    `json:"-"`
	AccessibleQueueIDs  []uint  `json:"-"` // Queue IDs user has permission to view (for permission filtering)
}

TicketListRequest represents query parameters for listing tickets.

type TicketListResponse

type TicketListResponse struct {
	Tickets    []Ticket `json:"tickets"`
	Total      int      `json:"total"`
	Page       int      `json:"page"`
	PerPage    int      `json:"per_page"`
	TotalPages int      `json:"total_pages"`
}

TicketListResponse represents a paginated list of tickets.

type TicketMerge

type TicketMerge struct {
	ID             uint       `json:"id"`
	ParentTicketID uint       `json:"parent_ticket_id" binding:"required"`
	ChildTicketID  uint       `json:"child_ticket_id" binding:"required"`
	MergedBy       uint       `json:"merged_by" binding:"required"`
	MergedAt       time.Time  `json:"merged_at"`
	UnmergedBy     *uint      `json:"unmerged_by,omitempty"`
	UnmergedAt     *time.Time `json:"unmerged_at,omitempty"`
	Reason         string     `json:"reason"`
	Notes          string     `json:"notes,omitempty"`
	IsActive       bool       `json:"is_active"`
}

TicketMerge represents a merge operation between tickets.

type TicketPriority

type TicketPriority struct {
	ID         uint      `json:"id" db:"id"`
	Name       string    `json:"name" db:"name"`
	ValidID    int       `json:"valid_id" db:"valid_id"`
	Color      string    `json:"color" db:"color"`
	CreateTime time.Time `json:"create_time" db:"create_time"`
	CreateBy   uint      `json:"create_by" db:"create_by"`
	ChangeTime time.Time `json:"change_time" db:"change_time"`
	ChangeBy   uint      `json:"change_by" db:"change_by"`
}

TicketPriority represents the priority level of a ticket.

type TicketRelation

type TicketRelation struct {
	ID              uint      `json:"id"`
	TicketID        uint      `json:"ticket_id" binding:"required"`
	RelatedTicketID uint      `json:"related_ticket_id" binding:"required"`
	RelationType    string    `json:"relation_type" binding:"required"` // "parent", "child", "duplicate", "related", "blocks", "blocked_by"
	CreatedBy       uint      `json:"created_by"`
	CreatedAt       time.Time `json:"created_at"`
	Notes           string    `json:"notes,omitempty"`
}

TicketRelation represents a relationship between tickets.

type TicketSLA

type TicketSLA struct {
	ID                 uint       `json:"id"`
	TicketID           uint       `json:"ticket_id"`
	SLAID              uint       `json:"sla_id"`
	FirstResponseDue   *time.Time `json:"first_response_due,omitempty"`
	FirstResponseAt    *time.Time `json:"first_response_at,omitempty"`
	NextUpdateDue      *time.Time `json:"next_update_due,omitempty"`
	LastUpdateAt       *time.Time `json:"last_update_at,omitempty"`
	SolutionDue        *time.Time `json:"solution_due,omitempty"`
	SolutionAt         *time.Time `json:"solution_at,omitempty"`
	Status             string     `json:"status"` // "pending", "in_progress", "breached", "met"
	BreachTime         *time.Time `json:"breach_time,omitempty"`
	EscalationLevel    int        `json:"escalation_level"`
	LastEscalationAt   *time.Time `json:"last_escalation_at,omitempty"`
	PausedAt           *time.Time `json:"paused_at,omitempty"`
	TotalPausedMinutes int        `json:"total_paused_minutes"`
	CreatedAt          time.Time  `json:"created_at"`
	UpdatedAt          time.Time  `json:"updated_at"`
}

TicketSLA tracks SLA compliance for a ticket.

type TicketSearchDocument

type TicketSearchDocument struct {
	ID            string     `json:"id"`
	TicketNumber  string     `json:"ticket_number"`
	Title         string     `json:"title"`
	Content       string     `json:"content"`
	Status        string     `json:"status"`
	Priority      string     `json:"priority"`
	Queue         string     `json:"queue"`
	CustomerName  string     `json:"customer_name"`
	CustomerEmail string     `json:"customer_email"`
	AgentName     string     `json:"agent_name"`
	AgentEmail    string     `json:"agent_email"`
	Tags          []string   `json:"tags"`
	CreatedAt     time.Time  `json:"created_at"`
	UpdatedAt     time.Time  `json:"updated_at"`
	ResolvedAt    *time.Time `json:"resolved_at,omitempty"`

	// Additional searchable content
	Messages      []string `json:"messages"`
	InternalNotes []string `json:"internal_notes"`
	Attachments   []string `json:"attachment_names"`
}

TicketSearchDocument represents a ticket in the search index.

type TicketState

type TicketState struct {
	ID         uint      `json:"id" db:"id"`
	Name       string    `json:"name" db:"name"`
	TypeID     int       `json:"type_id" db:"type_id"` // 1=new, 2=open, 3=closed, 4=removed, 5=pending
	Comments   *string   `json:"comments,omitempty" db:"comments"`
	ValidID    int       `json:"valid_id" db:"valid_id"`
	CreateTime time.Time `json:"create_time" db:"create_time"`
	CreateBy   uint      `json:"create_by" db:"create_by"`
	ChangeTime time.Time `json:"change_time" db:"change_time"`
	ChangeBy   uint      `json:"change_by" db:"change_by"`
}

TicketState represents the state of a ticket.

type TicketTemplate

type TicketTemplate struct {
	ID          uint      `json:"id"`
	Name        string    `json:"name" binding:"required"`
	Description string    `json:"description"`
	Category    string    `json:"category"` // e.g., "Technical", "Billing", "General"
	Subject     string    `json:"subject" binding:"required"`
	Body        string    `json:"body" binding:"required"`
	Priority    string    `json:"priority"`
	QueueID     int       `json:"queue_id"`
	TypeID      int       `json:"type_id"`
	Tags        []string  `json:"tags"`
	Active      bool      `json:"active"`
	UsageCount  int       `json:"usage_count"`
	CreatedBy   int       `json:"created_by"`
	UpdatedBy   int       `json:"updated_by"`
	CreatedAt   time.Time `json:"created_at"`
	UpdatedAt   time.Time `json:"updated_at"`

	// Template variables that can be replaced
	Variables []TemplateVariable `json:"variables"`

	// Attachments that should be included
	AttachmentURLs []string `json:"attachment_urls,omitempty"`
}

TicketTemplate represents a reusable template for common ticket types.

type TicketUpdateRequest

type TicketUpdateRequest struct {
	Title             *string `json:"title,omitempty" binding:"omitempty,min=1,max=255"`
	QueueID           *uint   `json:"queue_id,omitempty"`
	PriorityID        *uint   `json:"priority_id,omitempty"`
	StateID           *uint   `json:"state_id,omitempty"`
	UserID            *uint   `json:"user_id,omitempty"` // Owner
	ResponsibleUserID *uint   `json:"responsible_user_id,omitempty"`
	CustomerID        *uint   `json:"customer_id,omitempty"`
	CustomerUserID    *string `json:"customer_user_id,omitempty"`
	TicketLockID      *int    `json:"ticket_lock_id,omitempty"`
}

TicketUpdateRequest represents a request to update a ticket.

type TimeAccounting

type TimeAccounting struct {
	ID         int       `json:"id" db:"id"`
	TicketID   int       `json:"ticket_id" db:"ticket_id"`
	ArticleID  *int      `json:"article_id,omitempty" db:"article_id"`
	TimeUnit   int       `json:"time_unit" db:"time_unit"` // minutes
	CreateTime time.Time `json:"create_time" db:"create_time"`
	CreateBy   int       `json:"create_by" db:"create_by"`
	ChangeTime time.Time `json:"change_time" db:"change_time"`
	ChangeBy   int       `json:"change_by" db:"change_by"`
}

id, ticket_id, article_id, time_unit, create_time, create_by, change_time, change_by.

type TimeShift

type TimeShift struct {
	StartTime  string `json:"start_time"`            // Format: "09:00"
	EndTime    string `json:"end_time"`              // Format: "17:00"
	BreakStart string `json:"break_start,omitempty"` // Optional break
	BreakEnd   string `json:"break_end,omitempty"`
}

TimeShift represents a working shift.

type TransportConfig

type TransportConfig struct {
	Type   string              `yaml:"Type,omitempty" json:"type,omitempty"` // HTTP::REST, HTTP::SOAP
	Config TransportHTTPConfig `yaml:"Config,omitempty" json:"config,omitempty"`
}

TransportConfig defines the transport layer configuration.

type TransportHTTPConfig

type TransportHTTPConfig struct {
	// Common settings
	Host           string `yaml:"Host,omitempty" json:"host,omitempty"`
	DefaultCommand string `yaml:"DefaultCommand,omitempty" json:"default_command,omitempty"` // GET, POST, PUT, DELETE
	Timeout        string `yaml:"Timeout,omitempty" json:"timeout,omitempty"`                // seconds

	// REST-specific settings
	InvokerControllerMapping map[string]ControllerMapping `yaml:"InvokerControllerMapping,omitempty" json:"invoker_controller_mapping,omitempty"`

	// Provider REST settings
	RouteOperationMapping map[string]RouteMapping `yaml:"RouteOperationMapping,omitempty" json:"route_operation_mapping,omitempty"`
	MaxLength             string                  `yaml:"MaxLength,omitempty" json:"max_length,omitempty"`
	KeepAlive             string                  `yaml:"KeepAlive,omitempty" json:"keep_alive,omitempty"`
	AdditionalHeaders     map[string]string       `yaml:"AdditionalHeaders,omitempty" json:"additional_headers,omitempty"`

	// SOAP-specific settings
	Encoding   string `yaml:"Encoding,omitempty" json:"encoding,omitempty"`
	Endpoint   string `yaml:"Endpoint,omitempty" json:"endpoint,omitempty"`
	NameSpace  string `yaml:"NameSpace,omitempty" json:"namespace,omitempty"`
	SOAPAction string `yaml:"SOAPAction,omitempty" json:"soap_action,omitempty"`

	// Authentication
	Authentication AuthConfig `yaml:"Authentication,omitempty" json:"authentication,omitempty"`

	// SSL settings
	SSL SSLConfig `yaml:"SSL,omitempty" json:"ssl,omitempty"`

	// Proxy settings
	Proxy ProxyConfig `yaml:"Proxy,omitempty" json:"proxy,omitempty"`
}

TransportHTTPConfig defines HTTP transport settings.

type TrendPoint

type TrendPoint struct {
	Time  time.Time `json:"time"`
	Value int       `json:"value"`
}

TrendPoint represents a point in a trend graph.

type Trigger

type Trigger struct {
	ID         int             `json:"id"`
	WorkflowID int             `json:"workflow_id"`
	Type       TriggerType     `json:"type"`
	Config     json.RawMessage `json:"config"` // Trigger-specific configuration
	IsActive   bool            `json:"is_active"`
}

Trigger represents a workflow trigger.

type TriggerConfig

type TriggerConfig struct {
	// For time-based triggers
	DelayMinutes      int  `json:"delay_minutes,omitempty"`
	BusinessHoursOnly bool `json:"business_hours_only,omitempty"`

	// For status change triggers
	FromStatus string `json:"from_status,omitempty"`
	ToStatus   string `json:"to_status,omitempty"`

	// For priority change triggers
	FromPriority string `json:"from_priority,omitempty"`
	ToPriority   string `json:"to_priority,omitempty"`

	// For webhook triggers
	WebhookURL    string `json:"webhook_url,omitempty"`
	WebhookSecret string `json:"webhook_secret,omitempty"`

	// For scheduled triggers
	ScheduleExpr string `json:"schedule_expr,omitempty"`
}

TriggerConfig represents trigger-specific configuration.

type TriggerType

type TriggerType string

TriggerType represents the type of trigger for a workflow.

const (
	TriggerTypeTicketCreated   TriggerType = "ticket_created"
	TriggerTypeTicketUpdated   TriggerType = "ticket_updated"
	TriggerTypeTicketAssigned  TriggerType = "ticket_assigned"
	TriggerTypeStatusChanged   TriggerType = "status_changed"
	TriggerTypePriorityChanged TriggerType = "priority_changed"
	TriggerTypeCustomerReply   TriggerType = "customer_reply"
	TriggerTypeAgentReply      TriggerType = "agent_reply"
	TriggerTypeTimeBasedSLA    TriggerType = "time_based_sla"
	TriggerTypeScheduled       TriggerType = "scheduled"
	TriggerTypeWebhook         TriggerType = "webhook"
)

type UnmergeRequest

type UnmergeRequest struct {
	TicketID     uint   `json:"ticket_id" binding:"required"`
	Reason       string `json:"reason" binding:"required"`
	ReopenTicket bool   `json:"reopen_ticket"`
}

UnmergeRequest represents a request to unmerge tickets.

type UpdateTicketRequest

type UpdateTicketRequest struct {
	Title             string `json:"title"`
	QueueID           uint   `json:"queue_id"`
	StateID           uint   `json:"state_id"`
	PriorityID        uint   `json:"priority_id"`
	OwnerID           uint   `json:"owner_id"`
	ResponsibleUserID uint   `json:"responsible_user_id"`
	TypeID            uint   `json:"type_id"`
	UpdateBy          uint   `json:"-"`
}

UpdateTicketRequest represents a request to update a ticket.

type User

type User struct {
	ID               uint       `json:"id" db:"id"`
	Login            string     `json:"login" db:"login"`
	Email            string     `json:"email"`     // Not in users table, use login as email
	Password         string     `json:"-" db:"pw"` // Never expose in JSON
	Title            string     `json:"title" db:"title"`
	FirstName        string     `json:"first_name" db:"first_name"`
	LastName         string     `json:"last_name" db:"last_name"`
	ValidID          int        `json:"valid_id" db:"valid_id"` // OTRS valid field (1=valid, 2=invalid, 3=invalid-temporarily)
	CreateTime       time.Time  `json:"create_time" db:"create_time"`
	CreateBy         int        `json:"create_by" db:"create_by"`
	ChangeTime       time.Time  `json:"change_time" db:"change_time"`
	ChangeBy         int        `json:"change_by" db:"change_by"`
	Role             string     `json:"role"`                        // Admin, Agent, Customer
	IsInAdminGroup   bool       `json:"is_in_admin_group,omitempty"` // User is in admin group (for nav display)
	TenantID         uint       `json:"tenant_id,omitempty"`
	LastLogin        *time.Time `json:"last_login,omitempty"`
	FailedLoginCount int        `json:"-"`
	LockedUntil      *time.Time `json:"-"`
	Groups           []string   `json:"groups,omitempty"` // Group names for the user
}

func (*User) CheckPassword

func (u *User) CheckPassword(password string) bool

func (*User) IncrementFailedLogin

func (u *User) IncrementFailedLogin()

func (*User) IsActive

func (u *User) IsActive() bool

IsActive returns true if the user is active (valid_id = 1 in OTRS).

func (*User) IsLocked

func (u *User) IsLocked() bool

func (*User) LockAccount

func (u *User) LockAccount(duration time.Duration)

func (*User) ResetFailedLogin

func (u *User) ResetFailedLogin()

func (*User) SetPassword

func (u *User) SetPassword(password string) error

func (*User) UnlockAccount

func (u *User) UnlockAccount()

type UserRole

type UserRole string
const (
	RoleAdmin    UserRole = "Admin"
	RoleAgent    UserRole = "Agent"
	RoleCustomer UserRole = "Customer"
)

type Vendor

type Vendor struct {
	ID          uint   `json:"id" gorm:"primaryKey"`
	VendorCode  string `json:"vendor_code" gorm:"uniqueIndex;not null"`
	Name        string `json:"name" gorm:"not null"`
	Description string `json:"description"`
	Type        string `json:"type"`   // hardware, software, service
	Status      string `json:"status"` // active, inactive, blacklisted

	// Contact information
	ContactName  string `json:"contact_name"`
	ContactEmail string `json:"contact_email"`
	ContactPhone string `json:"contact_phone"`
	Address      string `json:"address"`
	City         string `json:"city"`
	State        string `json:"state"`
	Country      string `json:"country"`
	PostalCode   string `json:"postal_code"`
	Website      string `json:"website"`

	// Contract information
	ContractNumber string     `json:"contract_number"`
	ContractStart  *time.Time `json:"contract_start"`
	ContractEnd    *time.Time `json:"contract_end"`
	ContractValue  float64    `json:"contract_value"`
	PaymentTerms   string     `json:"payment_terms"`
	SupportLevel   string     `json:"support_level"`
	SupportPhone   string     `json:"support_phone"`
	SupportEmail   string     `json:"support_email"`

	// Performance metrics
	Rating        float64 `json:"rating"` // 1-5 scale
	DeliveryScore float64 `json:"delivery_score"`
	QualityScore  float64 `json:"quality_score"`
	ResponseTime  int     `json:"response_time"` // Hours

	// Audit fields
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

Vendor represents a vendor/supplier.

type WebserviceConfig

type WebserviceConfig struct {
	ID         int                   `json:"id"`
	Name       string                `json:"name"`
	Config     *WebserviceConfigData `json:"config,omitempty"`
	ConfigRaw  []byte                `json:"-"` // Raw YAML from database
	ValidID    int                   `json:"valid_id"`
	CreateTime time.Time             `json:"create_time"`
	CreateBy   int                   `json:"create_by"`
	ChangeTime time.Time             `json:"change_time"`
	ChangeBy   int                   `json:"change_by"`
}

WebserviceConfig represents a GenericInterface webservice configuration. Stored in gi_webservice_config table.

func (*WebserviceConfig) GetInvoker

func (w *WebserviceConfig) GetInvoker(name string) *InvokerConfig

GetInvoker returns an invoker by name from the Requester config.

func (*WebserviceConfig) GetOperation

func (w *WebserviceConfig) GetOperation(name string) *OperationConfig

GetOperation returns an operation by name from the Provider config.

func (*WebserviceConfig) InvokerNames

func (w *WebserviceConfig) InvokerNames() []string

InvokerNames returns a list of all invoker names.

func (*WebserviceConfig) IsValid

func (w *WebserviceConfig) IsValid() bool

IsValid returns true if the webservice is active.

func (*WebserviceConfig) OperationNames

func (w *WebserviceConfig) OperationNames() []string

OperationNames returns a list of all operation names.

func (*WebserviceConfig) RequesterHost

func (w *WebserviceConfig) RequesterHost() string

RequesterHost returns the requester transport host URL.

func (*WebserviceConfig) TransportType

func (w *WebserviceConfig) TransportType() string

TransportType returns the requester transport type (HTTP::REST, HTTP::SOAP).

type WebserviceConfigData

type WebserviceConfigData struct {
	Name             string          `yaml:"Name,omitempty" json:"name,omitempty"`
	Description      string          `yaml:"Description,omitempty" json:"description,omitempty"`
	RemoteSystem     string          `yaml:"RemoteSystem,omitempty" json:"remote_system,omitempty"`
	FrameworkVersion string          `yaml:"FrameworkVersion,omitempty" json:"framework_version,omitempty"`
	Debugger         DebuggerConfig  `yaml:"Debugger,omitempty" json:"debugger,omitempty"`
	Provider         ProviderConfig  `yaml:"Provider,omitempty" json:"provider,omitempty"`
	Requester        RequesterConfig `yaml:"Requester,omitempty" json:"requester,omitempty"`
}

WebserviceConfigData represents the parsed YAML configuration. Structure matches OTRS's GenericInterface config format.

type WebserviceConfigHistory

type WebserviceConfigHistory struct {
	ID         int64     `json:"id"`
	ConfigID   int       `json:"config_id"`
	Config     []byte    `json:"config"`
	ConfigMD5  string    `json:"config_md5"`
	CreateTime time.Time `json:"create_time"`
	CreateBy   int       `json:"create_by"`
	ChangeTime time.Time `json:"change_time"`
	ChangeBy   int       `json:"change_by"`
}

WebserviceConfigHistory represents a historical version of a webservice config.

type Workflow

type Workflow struct {
	ID          int            `json:"id"`
	Name        string         `json:"name"`
	Description string         `json:"description"`
	Status      WorkflowStatus `json:"status"`
	Priority    int            `json:"priority"` // Higher priority workflows execute first
	Triggers    []Trigger      `json:"triggers"`
	Conditions  []Condition    `json:"conditions"`
	Actions     []Action       `json:"actions"`
	CreatedBy   int            `json:"created_by"`
	CreatedAt   time.Time      `json:"created_at"`
	UpdatedAt   time.Time      `json:"updated_at"`
	LastRunAt   *time.Time     `json:"last_run_at"`
	RunCount    int            `json:"run_count"`
	ErrorCount  int            `json:"error_count"`
	IsSystem    bool           `json:"is_system"` // System workflows cannot be deleted
	Tags        []string       `json:"tags"`
}

Workflow represents an automation workflow.

func (*Workflow) EvaluateConditions

func (w *Workflow) EvaluateConditions(context map[string]interface{}) bool

EvaluateConditions evaluates all conditions for the workflow.

func (*Workflow) IsTriggeredBy

func (w *Workflow) IsTriggeredBy(triggerType TriggerType, context map[string]interface{}) bool

IsTriggeredBy checks if workflow should be triggered by given event.

func (*Workflow) Validate

func (w *Workflow) Validate() error

WorkflowValidation performs validation on a workflow.

type WorkflowExecution

type WorkflowExecution struct {
	ID            int                      `json:"id"`
	WorkflowID    int                      `json:"workflow_id"`
	WorkflowName  string                   `json:"workflow_name"`
	TicketID      int                      `json:"ticket_id"`
	TriggerType   TriggerType              `json:"trigger_type"`
	StartedAt     time.Time                `json:"started_at"`
	CompletedAt   *time.Time               `json:"completed_at"`
	Status        string                   `json:"status"` // success, failed, partial
	ActionsRun    int                      `json:"actions_run"`
	ActionsFailed int                      `json:"actions_failed"`
	ExecutionLog  []WorkflowExecutionEntry `json:"execution_log"`
	ErrorMessage  string                   `json:"error_message,omitempty"`
}

WorkflowExecution represents a single execution of a workflow.

type WorkflowExecutionEntry

type WorkflowExecutionEntry struct {
	Timestamp  time.Time  `json:"timestamp"`
	ActionType ActionType `json:"action_type"`
	ActionID   int        `json:"action_id"`
	Status     string     `json:"status"` // started, completed, failed
	Message    string     `json:"message"`
	Error      string     `json:"error,omitempty"`
	Duration   int64      `json:"duration_ms"`
	RetryCount int        `json:"retry_count"`
}

WorkflowExecutionEntry represents a single step in workflow execution.

type WorkflowSchedule

type WorkflowSchedule struct {
	ID         int        `json:"id"`
	WorkflowID int        `json:"workflow_id"`
	CronExpr   string     `json:"cron_expression"` // Cron expression for scheduling
	Timezone   string     `json:"timezone"`
	IsActive   bool       `json:"is_active"`
	LastRunAt  *time.Time `json:"last_run_at"`
	NextRunAt  time.Time  `json:"next_run_at"`
	CreatedAt  time.Time  `json:"created_at"`
}

WorkflowSchedule represents a scheduled workflow.

type WorkflowStatus

type WorkflowStatus string

WorkflowStatus represents the status of a workflow.

const (
	WorkflowStatusDraft    WorkflowStatus = "draft"
	WorkflowStatusActive   WorkflowStatus = "active"
	WorkflowStatusInactive WorkflowStatus = "inactive"
	WorkflowStatusArchived WorkflowStatus = "archived"
)

type WorkflowTemplate

type WorkflowTemplate struct {
	ID          int       `json:"id"`
	Name        string    `json:"name"`
	Description string    `json:"description"`
	Category    string    `json:"category"` // escalation, notification, assignment, etc.
	Icon        string    `json:"icon"`
	Config      Workflow  `json:"config"`
	IsPublic    bool      `json:"is_public"`
	UsageCount  int       `json:"usage_count"`
	CreatedAt   time.Time `json:"created_at"`
}

WorkflowTemplate represents a pre-built workflow template.

type WorkingDay

type WorkingDay struct {
	Day       DayOfWeek   `json:"day"`
	IsWorking bool        `json:"is_working"`
	Shifts    []TimeShift `json:"shifts"` // Multiple shifts per day support
}

WorkingDay defines working hours for a specific day.

type WorkingHours

type WorkingHours struct {
	DayOfWeek    int    `json:"day_of_week"` // 0=Sunday, 6=Saturday
	StartTime    string `json:"start_time"`  // HH:MM format
	EndTime      string `json:"end_time"`    // HH:MM format
	IsWorkingDay bool   `json:"is_working_day"`
}

WorkingHours defines working hours for each day.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL