226 lines
10 KiB
MySQL
226 lines
10 KiB
MySQL
|
|
-- Migration 014: Email Workflows System
|
||
|
|
-- Automatic actions based on email classification categories
|
||
|
|
|
||
|
|
-- Email Workflows Table
|
||
|
|
CREATE TABLE email_workflows (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
name VARCHAR(255) NOT NULL,
|
||
|
|
description TEXT,
|
||
|
|
|
||
|
|
-- Trigger Conditions
|
||
|
|
classification_trigger VARCHAR(50) NOT NULL, -- invoice, freight_note, time_confirmation, etc.
|
||
|
|
sender_pattern VARCHAR(255), -- Optional: only for emails from specific senders
|
||
|
|
subject_pattern VARCHAR(255), -- Optional: regex pattern for subject
|
||
|
|
confidence_threshold DECIMAL(3,2) DEFAULT 0.70, -- Minimum AI confidence to trigger
|
||
|
|
|
||
|
|
-- Workflow Steps (JSON array of actions to perform)
|
||
|
|
workflow_steps JSONB NOT NULL, -- [{"action": "create_ticket", "params": {...}}, ...]
|
||
|
|
|
||
|
|
-- Priority and Status
|
||
|
|
priority INTEGER DEFAULT 100, -- Lower number = higher priority
|
||
|
|
enabled BOOLEAN DEFAULT true,
|
||
|
|
stop_on_match BOOLEAN DEFAULT true, -- Stop processing other workflows if this matches
|
||
|
|
|
||
|
|
-- Statistics
|
||
|
|
execution_count INTEGER DEFAULT 0,
|
||
|
|
success_count INTEGER DEFAULT 0,
|
||
|
|
failure_count INTEGER DEFAULT 0,
|
||
|
|
last_executed_at TIMESTAMP,
|
||
|
|
|
||
|
|
-- Audit
|
||
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
created_by_user_id INTEGER,
|
||
|
|
|
||
|
|
FOREIGN KEY (created_by_user_id) REFERENCES users(user_id) ON DELETE SET NULL
|
||
|
|
);
|
||
|
|
|
||
|
|
-- Workflow Execution Log Table
|
||
|
|
CREATE TABLE email_workflow_executions (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
workflow_id INTEGER NOT NULL,
|
||
|
|
email_id INTEGER NOT NULL,
|
||
|
|
|
||
|
|
-- Execution Details
|
||
|
|
status VARCHAR(50) NOT NULL, -- pending, running, completed, failed, skipped
|
||
|
|
steps_completed INTEGER DEFAULT 0,
|
||
|
|
steps_total INTEGER,
|
||
|
|
|
||
|
|
-- Results
|
||
|
|
result_json JSONB, -- Store results from each step
|
||
|
|
error_message TEXT,
|
||
|
|
|
||
|
|
-- Timing
|
||
|
|
started_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
completed_at TIMESTAMP,
|
||
|
|
execution_time_ms INTEGER,
|
||
|
|
|
||
|
|
FOREIGN KEY (workflow_id) REFERENCES email_workflows(id) ON DELETE CASCADE,
|
||
|
|
FOREIGN KEY (email_id) REFERENCES email_messages(id) ON DELETE CASCADE
|
||
|
|
);
|
||
|
|
|
||
|
|
-- Workflow Step Actions Table (for pre-defined actions)
|
||
|
|
CREATE TABLE email_workflow_actions (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
action_code VARCHAR(100) UNIQUE NOT NULL,
|
||
|
|
name VARCHAR(255) NOT NULL,
|
||
|
|
description TEXT,
|
||
|
|
category VARCHAR(50), -- ticket_creation, notification, linking, extraction, etc.
|
||
|
|
|
||
|
|
-- Action Schema (defines what parameters this action accepts)
|
||
|
|
parameter_schema JSONB, -- JSON Schema for validation
|
||
|
|
|
||
|
|
-- Examples
|
||
|
|
example_config JSONB,
|
||
|
|
|
||
|
|
-- Status
|
||
|
|
enabled BOOLEAN DEFAULT true,
|
||
|
|
|
||
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||
|
|
);
|
||
|
|
|
||
|
|
-- Indexes for Performance
|
||
|
|
CREATE INDEX idx_email_workflows_classification ON email_workflows(classification_trigger) WHERE enabled = true;
|
||
|
|
CREATE INDEX idx_email_workflows_priority ON email_workflows(priority, enabled);
|
||
|
|
CREATE INDEX idx_email_workflow_executions_workflow ON email_workflow_executions(workflow_id);
|
||
|
|
CREATE INDEX idx_email_workflow_executions_email ON email_workflow_executions(email_id);
|
||
|
|
CREATE INDEX idx_email_workflow_executions_status ON email_workflow_executions(status);
|
||
|
|
|
||
|
|
-- Update Trigger
|
||
|
|
CREATE OR REPLACE FUNCTION update_email_workflows_updated_at()
|
||
|
|
RETURNS TRIGGER AS $$
|
||
|
|
BEGIN
|
||
|
|
NEW.updated_at = CURRENT_TIMESTAMP;
|
||
|
|
RETURN NEW;
|
||
|
|
END;
|
||
|
|
$$ LANGUAGE plpgsql;
|
||
|
|
|
||
|
|
CREATE TRIGGER trigger_email_workflows_updated_at
|
||
|
|
BEFORE UPDATE ON email_workflows
|
||
|
|
FOR EACH ROW
|
||
|
|
EXECUTE FUNCTION update_email_workflows_updated_at();
|
||
|
|
|
||
|
|
-- Insert Default Workflow Actions
|
||
|
|
INSERT INTO email_workflow_actions (action_code, name, description, category, parameter_schema, example_config) VALUES
|
||
|
|
|
||
|
|
-- Ticket/Case Creation
|
||
|
|
('create_ticket', 'Create Support Ticket', 'Creates a new support ticket/case from email', 'ticket_creation',
|
||
|
|
'{"type": "object", "properties": {"module": {"type": "string"}, "priority": {"type": "string"}, "assign_to": {"type": "integer"}}}',
|
||
|
|
'{"module": "support_cases", "priority": "normal", "assign_to": null}'),
|
||
|
|
|
||
|
|
('create_time_entry', 'Create Time Entry', 'Creates a time tracking entry from email', 'time_tracking',
|
||
|
|
'{"type": "object", "properties": {"customer_id": {"type": "integer"}, "hours": {"type": "number"}, "extract_from": {"type": "string"}}}',
|
||
|
|
'{"extract_from": "body", "default_hours": 1.0}'),
|
||
|
|
|
||
|
|
-- Linking Actions
|
||
|
|
('link_to_vendor', 'Link to Vendor', 'Links email to vendor based on sender', 'linking',
|
||
|
|
'{"type": "object", "properties": {"match_by": {"type": "string", "enum": ["email", "name", "cvr"]}, "auto_create": {"type": "boolean"}}}',
|
||
|
|
'{"match_by": "email", "auto_create": false}'),
|
||
|
|
|
||
|
|
('link_to_customer', 'Link to Customer', 'Links email to customer', 'linking',
|
||
|
|
'{"type": "object", "properties": {"match_by": {"type": "string"}, "domain_matching": {"type": "boolean"}}}',
|
||
|
|
'{"match_by": "email_domain", "domain_matching": true}'),
|
||
|
|
|
||
|
|
-- Extraction Actions
|
||
|
|
('extract_invoice_data', 'Extract Invoice Data', 'Extracts invoice number, amount, due date', 'extraction',
|
||
|
|
'{"type": "object", "properties": {"ai_provider": {"type": "string"}, "fallback_to_regex": {"type": "boolean"}}}',
|
||
|
|
'{"ai_provider": "ollama", "fallback_to_regex": true}'),
|
||
|
|
|
||
|
|
('extract_tracking_number', 'Extract Tracking Number', 'Extracts shipment tracking numbers', 'extraction',
|
||
|
|
'{"type": "object", "properties": {"carriers": {"type": "array", "items": {"type": "string"}}}}',
|
||
|
|
'{"carriers": ["postnord", "gls", "dao"]}'),
|
||
|
|
|
||
|
|
-- Notification Actions
|
||
|
|
('send_slack_notification', 'Send Slack Notification', 'Posts notification to Slack channel', 'notification',
|
||
|
|
'{"type": "object", "properties": {"channel": {"type": "string"}, "mention": {"type": "string"}, "template": {"type": "string"}}}',
|
||
|
|
'{"channel": "#invoices", "template": "New invoice from {{sender}}: {{subject}}"}'),
|
||
|
|
|
||
|
|
('send_email_notification', 'Send Email Notification', 'Sends email notification to user/team', 'notification',
|
||
|
|
'{"type": "object", "properties": {"recipients": {"type": "array"}, "template": {"type": "string"}}}',
|
||
|
|
'{"recipients": ["admin@bmcnetworks.dk"], "template": "default"}'),
|
||
|
|
|
||
|
|
-- Status Changes
|
||
|
|
('mark_as_processed', 'Mark as Processed', 'Updates email status to processed', 'status',
|
||
|
|
'{"type": "object", "properties": {"status": {"type": "string"}}}',
|
||
|
|
'{"status": "processed"}'),
|
||
|
|
|
||
|
|
('flag_for_review', 'Flag for Manual Review', 'Flags email for human review', 'status',
|
||
|
|
'{"type": "object", "properties": {"reason": {"type": "string"}, "assign_to": {"type": "integer"}}}',
|
||
|
|
'{"reason": "Low confidence classification", "assign_to": null}'),
|
||
|
|
|
||
|
|
-- Conditional Actions
|
||
|
|
('conditional_branch', 'Conditional Branch', 'Executes different actions based on conditions', 'control_flow',
|
||
|
|
'{"type": "object", "properties": {"condition": {"type": "string"}, "if_true": {"type": "array"}, "if_false": {"type": "array"}}}',
|
||
|
|
'{"condition": "confidence_score > 0.85", "if_true": [{"action": "create_ticket"}], "if_false": [{"action": "flag_for_review"}]}');
|
||
|
|
|
||
|
|
-- Insert Example Workflows
|
||
|
|
INSERT INTO email_workflows (name, description, classification_trigger, confidence_threshold, workflow_steps, priority, enabled) VALUES
|
||
|
|
|
||
|
|
-- Invoice Workflow
|
||
|
|
('Invoice Processing', 'Automatic processing of invoice emails', 'invoice', 0.70,
|
||
|
|
'[
|
||
|
|
{"action": "link_to_vendor", "params": {"match_by": "email", "auto_create": false}},
|
||
|
|
{"action": "extract_invoice_data", "params": {"ai_provider": "ollama", "fallback_to_regex": true}},
|
||
|
|
{"action": "create_ticket", "params": {"module": "billing_invoices", "priority": "normal"}},
|
||
|
|
{"action": "send_slack_notification", "params": {"channel": "#invoices", "template": "New invoice from {{sender}}: {{extracted_invoice_number}}"}},
|
||
|
|
{"action": "mark_as_processed", "params": {"status": "processed"}}
|
||
|
|
]'::jsonb, 10, true),
|
||
|
|
|
||
|
|
-- Time Confirmation Workflow
|
||
|
|
('Time Confirmation Processing', 'Process time tracking confirmations', 'time_confirmation', 0.65,
|
||
|
|
'[
|
||
|
|
{"action": "link_to_customer", "params": {"match_by": "email_domain", "domain_matching": true}},
|
||
|
|
{"action": "create_time_entry", "params": {"extract_from": "body", "default_hours": 1.0}},
|
||
|
|
{"action": "send_email_notification", "params": {"recipients": ["admin@bmcnetworks.dk"], "template": "time_confirmation"}},
|
||
|
|
{"action": "mark_as_processed", "params": {"status": "processed"}}
|
||
|
|
]'::jsonb, 20, true),
|
||
|
|
|
||
|
|
-- Freight Note Workflow
|
||
|
|
('Freight Note Processing', 'Track shipments from freight notes', 'freight_note', 0.70,
|
||
|
|
'[
|
||
|
|
{"action": "extract_tracking_number", "params": {"carriers": ["postnord", "gls", "dao"]}},
|
||
|
|
{"action": "link_to_vendor", "params": {"match_by": "email", "auto_create": false}},
|
||
|
|
{"action": "create_ticket", "params": {"module": "hardware_shipments", "priority": "low"}},
|
||
|
|
{"action": "mark_as_processed", "params": {"status": "processed"}}
|
||
|
|
]'::jsonb, 30, true),
|
||
|
|
|
||
|
|
-- Bankruptcy Alert Workflow
|
||
|
|
('Bankruptcy Alert', 'Alert team when customer bankruptcy detected', 'bankruptcy', 0.80,
|
||
|
|
'[
|
||
|
|
{"action": "flag_for_review", "params": {"reason": "Customer bankruptcy notification", "assign_to": null}},
|
||
|
|
{"action": "send_slack_notification", "params": {"channel": "#alerts", "template": "🚨 Bankruptcy alert: {{subject}}"}},
|
||
|
|
{"action": "send_email_notification", "params": {"recipients": ["admin@bmcnetworks.dk"], "template": "bankruptcy_alert"}},
|
||
|
|
{"action": "mark_as_processed", "params": {"status": "flagged"}}
|
||
|
|
]'::jsonb, 5, true),
|
||
|
|
|
||
|
|
-- Low Confidence Review Workflow
|
||
|
|
('Low Confidence Review', 'Flag emails with uncertain classification', 'general', 0.50,
|
||
|
|
'[
|
||
|
|
{"action": "flag_for_review", "params": {"reason": "Low confidence classification", "assign_to": null}}
|
||
|
|
]'::jsonb, 90, true);
|
||
|
|
|
||
|
|
-- View for workflow monitoring
|
||
|
|
CREATE OR REPLACE VIEW v_workflow_stats AS
|
||
|
|
SELECT
|
||
|
|
wf.id,
|
||
|
|
wf.name,
|
||
|
|
wf.classification_trigger,
|
||
|
|
wf.enabled,
|
||
|
|
wf.execution_count,
|
||
|
|
wf.success_count,
|
||
|
|
wf.failure_count,
|
||
|
|
ROUND((wf.success_count::numeric / NULLIF(wf.execution_count, 0) * 100), 2) as success_rate,
|
||
|
|
wf.last_executed_at,
|
||
|
|
COUNT(wfe.id) as pending_executions,
|
||
|
|
wf.created_at,
|
||
|
|
wf.updated_at
|
||
|
|
FROM email_workflows wf
|
||
|
|
LEFT JOIN email_workflow_executions wfe ON wf.id = wfe.workflow_id AND wfe.status = 'pending'
|
||
|
|
GROUP BY wf.id
|
||
|
|
ORDER BY wf.priority;
|
||
|
|
|
||
|
|
COMMENT ON TABLE email_workflows IS 'Automated workflows triggered by email classification';
|
||
|
|
COMMENT ON TABLE email_workflow_executions IS 'Log of all workflow executions';
|
||
|
|
COMMENT ON TABLE email_workflow_actions IS 'Registry of available workflow actions';
|
||
|
|
COMMENT ON VIEW v_workflow_stats IS 'Statistics and monitoring for email workflows';
|