205 lines
9.9 KiB
MySQL
205 lines
9.9 KiB
MySQL
|
|
-- Ticket Workflow Engine Tables
|
||
|
|
-- Refactors the monolithic workflow engine into a flexible, pipeline-like system
|
||
|
|
-- with per-workflow and per-step on/off switches, visual step editing, and
|
||
|
|
-- extensible step executors following the webhook pipeline engine pattern.
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- Ticket Workflows — workflow definitions (analogous to webhook_pipelines)
|
||
|
|
-- ============================================================================
|
||
|
|
CREATE TABLE IF NOT EXISTS ticket_workflows (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
name VARCHAR(200) NOT NULL,
|
||
|
|
description TEXT,
|
||
|
|
is_active BOOLEAN DEFAULT true,
|
||
|
|
trigger_event VARCHAR(50) NOT NULL, -- 'ticket.created', 'ticket.updated'
|
||
|
|
trigger_conditions JSONB NOT NULL DEFAULT '[]', -- array of {field, operator, value}
|
||
|
|
sort_order INTEGER DEFAULT 0,
|
||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- Ticket Workflow Steps — steps within a workflow (analogous to pipeline_steps)
|
||
|
|
-- ============================================================================
|
||
|
|
CREATE TABLE IF NOT EXISTS ticket_workflow_steps (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
workflow_id INTEGER NOT NULL REFERENCES ticket_workflows(id) ON DELETE CASCADE,
|
||
|
|
step_order INTEGER NOT NULL,
|
||
|
|
step_type VARCHAR(50) NOT NULL, -- 'classify','validate','ai_classify','ai_title','ai_troubleshooting','delay','update_ticket','filter'
|
||
|
|
name VARCHAR(200) NOT NULL,
|
||
|
|
config JSONB NOT NULL DEFAULT '{}', -- step-specific configuration
|
||
|
|
on_failure VARCHAR(20) DEFAULT 'continue', -- 'continue', 'stop', 'skip_to'
|
||
|
|
skip_to_step INTEGER,
|
||
|
|
is_active BOOLEAN DEFAULT true,
|
||
|
|
condition JSONB, -- optional condition to execute this step: {field, operator, value}
|
||
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- Ticket Workflow Executions — execution log (replaces workflow_executions)
|
||
|
|
-- ============================================================================
|
||
|
|
CREATE TABLE IF NOT EXISTS ticket_workflow_executions (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
workflow_id INTEGER NOT NULL REFERENCES ticket_workflows(id) ON DELETE CASCADE,
|
||
|
|
ticket_id BIGINT NOT NULL,
|
||
|
|
ticket_number VARCHAR(50),
|
||
|
|
status VARCHAR(20) NOT NULL DEFAULT 'pending', -- 'pending','running','completed','failed','skipped'
|
||
|
|
classification_method VARCHAR(20), -- 'robotic', 'ai', 'hybrid'
|
||
|
|
branch VARCHAR(20), -- 'service_desk', 'noc', 'soc'
|
||
|
|
context JSONB NOT NULL DEFAULT '{}', -- accumulated data from steps
|
||
|
|
field_changes JSONB, -- final changes applied to ticket
|
||
|
|
started_at TIMESTAMP DEFAULT NOW(),
|
||
|
|
completed_at TIMESTAMP,
|
||
|
|
duration_ms INTEGER,
|
||
|
|
error_message TEXT,
|
||
|
|
created_at TIMESTAMP DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- Ticket Workflow Execution Steps — per-step audit trail (replaces workflow_execution_steps)
|
||
|
|
-- ============================================================================
|
||
|
|
CREATE TABLE IF NOT EXISTS ticket_workflow_execution_steps (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
execution_id INTEGER NOT NULL REFERENCES ticket_workflow_executions(id) ON DELETE CASCADE,
|
||
|
|
step_order INTEGER NOT NULL,
|
||
|
|
step_type VARCHAR(50) NOT NULL,
|
||
|
|
step_name VARCHAR(200),
|
||
|
|
status VARCHAR(20) NOT NULL DEFAULT 'pending', -- 'pending','running','completed','failed','skipped'
|
||
|
|
input_data JSONB,
|
||
|
|
output_data JSONB,
|
||
|
|
started_at TIMESTAMP,
|
||
|
|
completed_at TIMESTAMP,
|
||
|
|
duration_ms INTEGER,
|
||
|
|
error_message TEXT
|
||
|
|
);
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- Indexes
|
||
|
|
-- ============================================================================
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ticket_workflows_event ON ticket_workflows(trigger_event, is_active, sort_order);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ticket_workflow_steps_workflow ON ticket_workflow_steps(workflow_id, step_order);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ticket_workflow_executions_workflow ON ticket_workflow_executions(workflow_id, created_at DESC);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ticket_workflow_executions_ticket ON ticket_workflow_executions(ticket_id, created_at DESC);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ticket_workflow_executions_status ON ticket_workflow_executions(status, created_at DESC);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ticket_workflow_execution_steps_exec ON ticket_workflow_execution_steps(execution_id, step_order);
|
||
|
|
|
||
|
|
-- ============================================================================
|
||
|
|
-- SEED: "Ticket Triage" Workflow (ports current hardcoded workflow-engine.ts logic)
|
||
|
|
-- ============================================================================
|
||
|
|
INSERT INTO ticket_workflows (name, description, is_active, trigger_event, trigger_conditions, sort_order) VALUES
|
||
|
|
('Ticket Triage',
|
||
|
|
'Automatically classifies new tickets using robotic keyword matching, validates the classification, enhances with AI when needed, and writes back to Autotask.',
|
||
|
|
true,
|
||
|
|
'ticket.created',
|
||
|
|
'[
|
||
|
|
{
|
||
|
|
"field": "ticket_category",
|
||
|
|
"operator": "in",
|
||
|
|
"value": [2, 3, 159, 161]
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"field": "creator_resource_id",
|
||
|
|
"operator": "not_in",
|
||
|
|
"value": [30861471]
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"field": "person_id",
|
||
|
|
"operator": "not_in",
|
||
|
|
"value": [30861575]
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"field": "company_id",
|
||
|
|
"operator": "not_in",
|
||
|
|
"value": [29861409, 29783545, 29861361, 29702433]
|
||
|
|
}
|
||
|
|
]',
|
||
|
|
10);
|
||
|
|
|
||
|
|
-- Step 1: Classify - Branch Routing
|
||
|
|
INSERT INTO ticket_workflow_steps (workflow_id, step_order, step_type, name, config, is_active) VALUES
|
||
|
|
((SELECT id FROM ticket_workflows WHERE name = 'Ticket Triage'), 1, 'classify', 'Branch Routing', '{
|
||
|
|
"rule_type": "branch_routing",
|
||
|
|
"result_field": "branch",
|
||
|
|
"default_value": "service_desk"
|
||
|
|
}', true);
|
||
|
|
|
||
|
|
-- Step 2: Classify - Ticket Type
|
||
|
|
INSERT INTO ticket_workflow_steps (workflow_id, step_order, step_type, name, config, is_active) VALUES
|
||
|
|
((SELECT id FROM ticket_workflows WHERE name = 'Ticket Triage'), 2, 'classify', 'Ticket Type', '{
|
||
|
|
"rule_type": "ticket_type",
|
||
|
|
"result_field": "ticket_type"
|
||
|
|
}', true);
|
||
|
|
|
||
|
|
-- Step 3: Classify - Issue Classification
|
||
|
|
INSERT INTO ticket_workflow_steps (workflow_id, step_order, step_type, name, config, is_active) VALUES
|
||
|
|
((SELECT id FROM ticket_workflows WHERE name = 'Ticket Triage'), 3, 'classify', 'Issue Classification', '{
|
||
|
|
"rule_type": "issue_classification",
|
||
|
|
"result_field": "issue_type",
|
||
|
|
"result_field_2": "sub_issue_type"
|
||
|
|
}', true);
|
||
|
|
|
||
|
|
-- Step 4: Classify - Priority
|
||
|
|
INSERT INTO ticket_workflow_steps (workflow_id, step_order, step_type, name, config, is_active) VALUES
|
||
|
|
((SELECT id FROM ticket_workflows WHERE name = 'Ticket Triage'), 4, 'classify', 'Priority', '{
|
||
|
|
"rule_type": "priority",
|
||
|
|
"result_field": "priority"
|
||
|
|
}', true);
|
||
|
|
|
||
|
|
-- Step 5: Classify - Queue Routing
|
||
|
|
INSERT INTO ticket_workflow_steps (workflow_id, step_order, step_type, name, config, is_active) VALUES
|
||
|
|
((SELECT id FROM ticket_workflows WHERE name = 'Ticket Triage'), 5, 'classify', 'Queue Routing', '{
|
||
|
|
"rule_type": "queue_routing",
|
||
|
|
"result_field": "queue_id"
|
||
|
|
}', true);
|
||
|
|
|
||
|
|
-- Step 6: Validate Classification
|
||
|
|
INSERT INTO ticket_workflow_steps (workflow_id, step_order, step_type, name, config, is_active, on_failure) VALUES
|
||
|
|
((SELECT id FROM ticket_workflows WHERE name = 'Ticket Triage'), 6, 'validate', 'Validate Classification', '{
|
||
|
|
"required_fields": []
|
||
|
|
}', true, 'continue');
|
||
|
|
|
||
|
|
-- Step 7: AI Classify (conditional - only if validation failed)
|
||
|
|
INSERT INTO ticket_workflow_steps (workflow_id, step_order, step_type, name, config, is_active, condition) VALUES
|
||
|
|
((SELECT id FROM ticket_workflows WHERE name = 'Ticket Triage'), 7, 'ai_classify', 'AI Classification', '{
|
||
|
|
"template_purpose": "ambiguous_classification",
|
||
|
|
"skip_if_valid": true
|
||
|
|
}', true, '{
|
||
|
|
"field": "context.validation.is_valid",
|
||
|
|
"operator": "equals",
|
||
|
|
"value": false
|
||
|
|
}');
|
||
|
|
|
||
|
|
-- Step 8: AI Title Cleanup (conditional - only if title needs cleanup)
|
||
|
|
INSERT INTO ticket_workflow_steps (workflow_id, step_order, step_type, name, config, is_active, condition) VALUES
|
||
|
|
((SELECT id FROM ticket_workflows WHERE name = 'Ticket Triage'), 8, 'ai_title', 'AI Title Cleanup', '{
|
||
|
|
"template_purpose": "title_cleanup"
|
||
|
|
}', true, '{
|
||
|
|
"field": "context.classification.ai_reasons",
|
||
|
|
"operator": "contains",
|
||
|
|
"value": "Title"
|
||
|
|
}');
|
||
|
|
|
||
|
|
-- Step 9: Delay before Autotask update
|
||
|
|
INSERT INTO ticket_workflow_steps (workflow_id, step_order, step_type, name, config, is_active) VALUES
|
||
|
|
((SELECT id FROM ticket_workflows WHERE name = 'Ticket Triage'), 9, 'delay', 'Delay Before Update', '{
|
||
|
|
"duration_ms": "{{settings.autotask_update_delay_ms}}"
|
||
|
|
}', true);
|
||
|
|
|
||
|
|
-- Step 10: Update Ticket in Autotask
|
||
|
|
INSERT INTO ticket_workflow_steps (workflow_id, step_order, step_type, name, config, is_active, on_failure) VALUES
|
||
|
|
((SELECT id FROM ticket_workflows WHERE name = 'Ticket Triage'), 10, 'update_ticket', 'Update Autotask Ticket', '{
|
||
|
|
"use_field_changes": true
|
||
|
|
}', true, 'stop');
|
||
|
|
|
||
|
|
-- Step 11: AI Troubleshooting (conditional - only for incidents)
|
||
|
|
INSERT INTO ticket_workflow_steps (workflow_id, step_order, step_type, name, config, is_active, condition) VALUES
|
||
|
|
((SELECT id FROM ticket_workflows WHERE name = 'Ticket Triage'), 11, 'ai_troubleshooting', 'Generate Troubleshooting Steps', '{
|
||
|
|
"template_purpose": "troubleshooting_steps",
|
||
|
|
"create_note": true
|
||
|
|
}', true, '{
|
||
|
|
"field": "context.field_changes.ticket_type.after",
|
||
|
|
"operator": "equals",
|
||
|
|
"value": 2
|
||
|
|
}');
|